1.主從複製
兩個Redis實例(可ip相同port不同),可使用slaveof命令設置主從關係。redis採用樂觀同步策略,即容忍短時間內主從不一致,但是保證最終一致性,主從複製分爲三個階段:
- 連接階段
- 數據同步階段
- 命令傳播階段
2.連接階段
當slave執行完salveof ${master_ip} ${master_port}命令時,slave向master發起socket連接,master接收到連接請求後建立連接。
當連接建立後,slave向master發送[ping]命令,以確定master狀態正常,如果master響應[pong]則代表master正常。
如果master設置了密碼,則slave需要配置masterauth參數,此時slave發送[auth + ${passwoed}]命令進行密碼驗證,
當密碼驗證成功後,slave通知master自己的監聽端口,此時連接完成。
3.數據同步階段
數據同步階段是slave的數據初始化階段,也就是slave同步master當前的數據,該步是slave主動發起。
slave向master發送[psync]命令,master收到請求後,首先判斷是增量複製還是全量複製,然後再同步。
增量複製是指master僅將緩衝區中的命令發給slave,slave依次執行命令,完成數據同步。
全量複製是指master先生成內存快照(rdb文件,這裏和是否開啓rdb備份無關),然後將內存快照發給slave,slave加載快照到內存中完成數據同步。
3.1 offset 偏移量
master和slave都會維護一個偏移量(可使用[info replication]命令查看偏移量),用於標識主從複製的現狀;master的offset表示向slave已發送的字節數,slave的offset表示已同步的字節數。可以通過offset觀察主從是否同步完成,若相等則說明同步完成。
3.2 replication backlog buffer
[replication backlog buffer]是一個固定長度的FIFO的隊列,大小由配置參數[repl-backlog]指定,默認大小是1mb,這個緩衝區只存在master,用於備份最近master同步slave的數據。
在命令傳播階段,master除了將命令同步給slave外還會在這個緩衝區中備份,而且還會存儲每個命令(實際是每個字節)對用的offset值,如下圖:
由於緩衝區固定大小,因此只能備份最近執行過的命令,這個緩衝區用於增量複製,提高數據同步階段的效率。
3.3 runid
每個redis服務每次啓動時,都會隨機生成一個40的id來代表自己,可通過[info server]命令查詢run_id。
在初次主從同步時,master會將自己的runid發送給slave,salve記錄自己的[master runid]。
3.4 同步流程
-
slave首先判斷是否第一次執行主從複製,即如果有保存的[master run_id],如果有則說明不是第一次。
-
如果slave是第一次執行主從複製,則向master發送全量複製請求。
-
如果slave不是第一次執行主從複製,則向master發送增量複製請求[ psync ${master run_id} offset ]。
-
master如果接受到全量複製請求,則進行內存快照,然後響應rdb文件。
-
master如果接受到增量複製請求,則首先判斷請求中的runid是不是自己,如果和自己的runid不一致,則說明slave之前的master並不是自己,此時只能進行全量複製,響應[ FULLRESYNC runid offset ],從節點則更新自己保存的master runid,並將offset作爲自己的初始偏移量,然後等待master發來的rdb文件進而執行全量複製。
-
如果master判斷slave的上一次的master是自己時,則繼續判斷請求中的offset是否在[replication-backlog-buffer]中,如果在則說明可以進行增量複製,返回[CONTINUE],slave則得知可以進行增量複製,等待slave發來的自己缺少的那部分命令,然後執行即可。
4 命令傳播階段
當數據同步完成後,此後的時間裏主從之間維護心跳來檢查對方是否在線。
master定時向slave發送[PING]請求,如果收到slave的[PONG]響應則可知slave在線(默認10s,通過參數[repl-ping-slave-period]指定)。
slave每秒向master發送[ REPLCONF ACK ${offset} ]命令,master根據偏移量響應未同步的數據,slave收到master的響應可知master在線,並執行命令,完成主從同步。