1、設置主服務器的地址和端口
首先是在從服務器設置需要同步的主服務器信息,包括機器IP, 端口。
主從復制的開啟,完全是在從節點發起的。不需要我們在主節點做任何事情。
從節點開啟主從復制,有3種方式
- 配置文件:在從服務器的配置文件中加入:slaveof 主機ip 主機port
- 啟動命令: redis-server啟動命令后加入 --slaveof 主機ip 主機port
- 客戶端命令: redis服務啟動后,在客戶端執行slaveof IP port命令,此時該實例稱為從節點.
2、建立socket套接字連接
在從節點執行完slave命令后,向主節點發起socket連接。
3、發送ping命令
發送ping命令進行首次請求,目的是:檢查socket連接是否可用,以及主節點當前是否能夠處理請求。
發送ping后可能會出現以下三種情況:
- 響應pong: 說明socket連接正常,且主節點當前可以處理請求,復制過程可以繼續
- 超市,從節點未收到回復,則斷開連接然后重試
- 返回pong以外的響應,比如正在處理超時的腳本等,說明主節點當前無法進行復制的過程,從節點斷開連接并重試。
4、身份權限驗證
- 如果從節點中設置了masterauth選項,則從節點需要向主節點進行身份驗證;沒有設置該選項,則不需要驗證。
- 從節點進行身份驗證是通過向主節點發送auth命令進行的,auth命令的參數即為配置文件中的masterauth的值。
- 如果主節點設置密碼的狀態,與從節點masterauth的狀態一致(一致是指都存在,且密碼相同,或者都不存在),則身份驗證通過,復制過程繼續;如果不一致,則從節點斷開socket連接,并重連。
5、同步數據(pysnc)
同步就是將從節點的數據庫狀態更新成主節點當前的數據庫狀態。具體執行的方式是:從節點向主節點發送psync命令(Redis2.8以前是sync命令),開始同步。 數據同步階段是主從復制最核心的階段,根據主從節點當前狀態的不同,可以分為全量復制和部分復制 。
6、命令持續復制
在數據同步之后,由于主節點不斷的接受到寫入命令,主從節點進入命令傳播階段,主節點將自己執行的寫命令發送給從節點,從節點接收命令并執行,從而保證主從節點數據的一致性。
注意:
- 命令傳播是異步的過程,即主節點發送寫命令后并不會等待從節點的回復;因此實際上主從節點之間很難保持實時的一致性,延遲在所難免。數據不一致的程度,與主從節點之間的網絡狀況、主節點寫命令的執行頻率、以及主節點中的repl-disable-tcp-nodelay配置等有關。
主從持續復制階段,從服務器會利用心跳檢測機制定時的向主服務發送消息。
7、全量復制和部分復制
- 全量復制:用于初次復制或其他無法進行部分復制的情況,將主節點中的所有數據都發送給從節點,是一個非常重型的操作。
- 部分復制:用于網絡中斷等情況后的復制,只將中斷期間主節點執行的寫命令發送給從節點,與全量復制相比更加高效。需要注意的是,如果網絡中斷時間過長,導致主節點沒有能夠完整地保存中斷期間執行的寫命令,則無法進行部分復制,仍使用全量復制。
全量復制的過程:
1.從節點判斷無法進行部分復制,向主節點發送全量復制的請求;或從節點發送部分復制的請求,但主節點判斷無法進行部分復制;
2.主節點收到全量復制的命令后,執行bgsave,在后臺生成RDB文件,并使用一個緩沖區(稱為復制緩沖區)記錄從現在開始執行的所有寫命令。
3.主節點的bgsave執行完成后,將RDB文件發送給從節點;從節點首先清除自己的舊數據,然后載入接收的RDB文件,將數據庫狀態更新至主節點執行bgsave時的數據庫狀態。
4.主節點將緩沖區中的所有寫命令發送給從節點,從節點執行這些寫命令,將數據庫狀態更新至主節點的最新狀態。
5.如果從節點開啟了AOF,則會觸發bgrewriteaof的執行,從而保證AOF文件更新至主節點的最新狀態。
全量復制流程圖:
通過全量復制的過程可以看出,全量復制是非常重型的操作:
1.主節點通過bgsave命令fork子進程進行RDB持久化,該過程是非常消耗CPU、內存(頁表復制)、硬盤IO的;
2.主節點通過網絡將RDB文件發送給從節點,對主從節點的帶寬都會帶來很大的消耗。
3.從節點清空老數據、載入新RDB文件的過程是阻塞的,無法響應客戶端的命令;如果從節點執行bgrewriteaof,也會帶來額外的消耗。
部分復制
由于全量復制在主節點數據量較大時效率太低,因此提供部分復制的方式。
部分復制依賴于三個重要的概念:
1.復制偏移量
2.復制積壓緩沖區
3.服務器運行ID(runid)
復制偏移量:
執行復制的雙方,主從節點,分別會維護一個復制偏移量offset: 主節點每次向從節點同步了N字節數據后,將修改自己的復制偏移量offset+N 從節點每次從主節點同步了N字節數據后,將修改自己的復制偏移量offset+N。
offset用于判斷主從節點的數據庫狀態是否一致: 如果二者offset相同,則一致; 如果offset不同,則不一致,此時可以根據兩個offset找出從節點缺少的那部分數據。
復制積壓緩沖區:
主節點內部維護了一個固定長度的、先進先出(FIFO)隊列 作為復制積壓緩沖區,其默認大小為1MB 在主節點進行命令傳播時,不僅會將寫命令同步到從節點,還會將寫命令寫入復制積壓緩沖區。
由于復制積壓緩沖區定長且是先進先出,所以它保存的是主節點最近執行的寫命令;
當主從節點offset的差距過大超過緩沖區長度時,將無法執行部分復制,只能執行全量復制。
為了提高網絡中斷時部分復制執行的概率,可以根據需要增大復制積壓緩沖區的大小(通過配置repl-backlog-size);例如如果網絡中斷的平均時間是60s,而主節點平均每秒產生的寫命令(特定協議格式)所占的字節數為100KB,則復制積壓緩沖區的平均需求為6MB,保險起見,可以設置為12MB,來保證絕大多數斷線情況都可以使用部分復制。
從節點將offset發送給主節點后,主節點根據offset和緩沖區大小決定能否執行部分復制:
如果offset偏移量之后的數據,仍然都在復制積壓緩沖區里,則執行部分復制;
如果offset偏移量之后的數據已不在復制積壓緩沖區中(數據已被擠出),則執行全量復制。
服務器運行ID(runid):
1.每個Redis節點,都有其運行ID。
2.運行ID由節點在啟動時自動生成。
3.主節點會將自己的運行ID發送給從節點,從節點會將主節點的運行ID存起來。
1.如果從節點保存的runid與主節點現在的runid相同,說明主從節點之前同步過,主節點會繼續嘗試使用部分復制(到底能不能部分復制還要看offset和復制積壓緩沖區的情況);
2.如果從節點保存的runid與主節點現在的runid不同,說明從節點在斷線前同步的Redis節點并不是當前的主節點,只能進行全量復制。
psync命令的大體流程
1.如果從節點之前沒有復制過任何主節點,或者之前執行過slaveof no one命令,從節點就會向主節點發送psync命令,請求主節點進行數據的全量同步
2.如果前面從節點已經同步過部分數據,此時從節點就會發送psync {runid} {offset}命令給主節點,其中runid是上一次主節點的運行ID,offset是當前從節點的復制偏移量。
主節點收到psync命令后,會出現以下三種可能:
1.主節點返回 fullresync {runid} {offset}回復,表示主節點要求與從節點進行數據的完整全量復制,其中runid表示主節點的運行ID,offset表示當前主節點的復制偏移量
2.如果主服務器返回 +continue,表示主節點與從節點會進行部分數據的同步操作,將從服務器缺失的數據復制過來即可。
3.如果主服務器返回 -err,表示主服務器的Redis版本低于2.8,無法識別psync命令,此時從服務器會向主服務器發送sync命令,進行完整的數據全量復制
心跳檢測機制的作用
1.檢查主從服務器的網絡連接狀態 //主節點信息中可以看到所屬的從節點的連接信息state 表示從節點狀態offset 表示復制偏移量lag 表示延遲值(幾秒之前有過心跳檢測機制)
2.輔助實現min-slaves選項//如果將兩個參數的注釋取消,那么如果從服務器的數量少于3個,或者三個從服務器的延遲(lag)大于等于10秒時,主服務器都會拒絕執行寫命令min-slaves-to-write 3 //min-slaves-to-write 3min-slaves-max-lag 10 //延遲值
3.檢測命令丟失 //在從服務器的連接信息中可以看到復制偏移量,如果此時主服務器的復制偏移量與從服務器的復制偏移量不一致時,主服務器會補發缺失的數據。