舊版複製實現
- 同步:將從服務器的數據庫狀態更新至主服務器當前所處的數據庫狀態
- 命令傳播:在主服務器的數據庫狀態被修改,導致主從服務器的數據庫狀態不一致時,讓主從服務器的數據庫重新回到一致狀態。當主服務器執行完命令之後,進行命令傳播操作,將命令發送給從服務器執行,從服務器執行了相同命令。主從服務器再次回到一致狀態。
缺陷
斷線後重複製,需同步所有數據。實際可能只是一小部分數據缺失。
新版複製實現
-
完整重同步:通過讓主服務器創建併發送RDB文件,以及向從服務器發送保存在緩衝區裏面寫命令來進行同步
-
部分重同步:當從服務器在斷線後重新連接主服務器時,如果條件允許,主服務器將主從服務器連接斷開期間執行的寫命令發送給從服務器。
部分重同步的實現
- 主服務器的複製偏移量和從服務器的複製偏移量
- 主服務器的複製積壓緩衝區
- 服務器的運行ID
複製偏移量
執行復制雙方------主服務器和從服務器分別維護一個複製偏移量:
主服務器每次向從服務器傳播N個字節的數據時,就將自己的複製偏移量的值增加N。
從服務器每次收到主服務器傳播來的N個字節數據時,將自己的複製偏移量的值加上N。
複製積壓緩衝區
複製積壓緩衝區是由主服務器維護的一個固定長度先進先出隊列(當入隊元素大於隊列長度時,最先入隊元素會被彈出)。默認大小1MB。可以根據second(斷線後重連平均時間)*write_size_per_second(平均每秒產生寫命令數據量)來估算設置repl-backlog-size選項改變緩衝區大小。
重連同步流程:
- 當從服務器A(上圖爲例)斷線重連後,向主服務器發送PSYNC命令,報告自己的偏移量爲10086
- 主服務器收到命令後,檢查偏移量10086之後的數據是否存在於複製積壓緩衝區裏。存在,向服務器發送+CONTINUE回覆,表示數據同步將以部分重同步模式進行。(不存在,主服務器將對從服務器執行完整重同步操作)
- 主服務器將複製積壓緩衝區10086之後的所有數據發送給從服務器
- 從服務器接收缺失數據,回到與主服務器一致的狀態
服務器運行ID
每個Redis服務器,不論主服務器還是從服務器,都會有自己的運行ID。從服務器在對主服務器進行初次複製時,保存該主服務器的運行ID。當斷線重連後,從服務器保存運行ID與連接的主服務器運行ID相同,可執行部分重同步。不同將執行完整重同步。
PSYNC命令流程圖
心跳檢測
在命令傳播階段,從服務器默認會以每秒一次的頻率,向主服務器發送命令:REPLCONF ACK <replication_offset>
其中replication_offset是從服務器當前的複製偏移量
- 檢測主從服務器的網絡連接狀態
- 輔助實現min-slaves選項。min-slaves-to-write和min-slaves-max-lag防止主服務器在不安全的情況下執行寫命令。
min-slaves-to-write 3 min-slaves-max-lag 10
在從服務器數量少於3個,或者三個從服務器的延遲值(最後一次心跳檢測距離現在過了多少秒)都大於或等於10秒時,主服務器將拒絕執行寫命令
- 檢測命令丟失。偏移量不一致,會進行補發缺失數據的操作(Redis 2.8之前會命令丟失)。