Redis學習筆記(十三) 複製(下)

上一篇寫了Redis複製功能的簡單應用,下面咱們看下Redis複製功能的實現過程。下面基本上是理論部分,枯燥乏味,但但願你們能看看,畢竟知識不都是感興趣的.
耐得住寂寞,經得起誘惑,方能守得住繁華 ~.~
舊版複製功能的實現數據庫

Redis的複製功能分爲同步和命令傳播兩個操做:安全

一、同步操做用於將從服務器的數據庫狀態更新至主服務器當前所處的數據庫狀態。服務器

二、命令傳播操做則用於在主服務器 的數據庫狀態被修改,致使從服務器的數據庫狀態出現不一致時,讓主服務器的數據庫從新回到一致狀態。網絡

從服務器對主服務器的同步操做須要經過向主服務發送sync命令來完成,如下是sync命令的執行步驟:學習

(1)從服務器向主服務器發送SYNC命令ui

(2)收到SYNC命令的主服務器執行BGSAVE命令,在後臺生成一個RDB文件,並使用一個緩衝區記錄如今開始執行的全部寫命令。設計

(3)當主服務器的BGSAVE命令執行完畢時,主服務器會BGSAVE命令生成的RDB文件發送給從服務器,從服務器接收並載入這個RDB文件,將本身的數據庫狀態更新至主服務器執行BGSAVE命令時的數據庫狀態。blog

(4)主服務器將記錄在緩衝區的全部寫命令發送給從服務器,從服務器執行這些寫命令,將本身的數據庫狀態更新至主服務器數據庫當前所處的狀態。隊列

命令傳播:當主服務器執行客戶端寫命令時,主服務器的數據庫就有可能被修改,並致使主從不一致。此時主服務器會將本身執行的寫命令發送給從服務器執行,當從服務器執行了相同的寫命令後,主從服務器再次回到一致狀態。事件

缺陷

一、初始複製從服務器歷來沒有複製過任何主服務器或者從服務器當前要複製的主服務器和上次複製的主服務器不一樣。

二、斷線後重複製:處於命令傳播階段的主從服務器由於網絡緣由而中斷了複製,但從服務器經過自動鏈接重新連上主服務器,並繼續複製。


新版複製功能的實現(PSYNC代替SYNC)

PSYNC命令具備完整重同步和部分重同步兩種模式:

(1)完整重同步用於處理初次複製功能,與SYNC功能基本一致;

(2)部分重同步用於處理斷線後重復值的狀況,解決舊版效率低的問題。

 

部分重同步的實現:

(1)主服務器與從服務器都會維護一個複製偏移量

(2)複製積壓緩衝區是由主服務器維護的一個固定長度先進先出的隊列默認(1MB),發生斷線從連時,但從服務器重連上主服務器,從服務器會經過PSYNC命令將本身的複製偏移量offset發送給主服務器,主服務器根據這個複製偏移量來決定對從服務器執行何種同步操做:若是offset偏移量以後的數據仍然存在於複製積壓緩衝區裏面,那麼主服務器將對從服務器執行部分重同步,反之,執行完整重同步操做。除了複製偏移量和複製積壓緩衝以外,實現部分重同步還須要用到服務器運行ID:每一個Redis服務器都有本身啓動時生成的由40個隨機16進制字符組成的運行ID。當服務器對主服務器進行初次複製時,主服務器會將本身的運行ID傳送給從服務器,而從服務器則會將這個運行ID保存起來。當服務器斷線重連時,從服務器向主服務器發送保存的運行ID,若是ID同樣,則主服務器嘗試部分重同步操做,若是不一樣,則執行完整重同步操做。

PSYNC命令的實現

PSYNC命令的實現方法有兩種:

1)若是從服務器之前沒有複製過任何主服務器,或者以前執行過SLAVEOF no one命令,那麼從服務器在開始新的複製時將向主服務器發送PSYNC? -1 命令,主動請求進行完整重同步。

(2)若是以前複製過某個主服務器,那麼從服務在開始一次新的複製時向主服務器發送PSYNC <runid> <offset>。由主服務器來判斷該用那種方式同步。

(3)若是主服務器返回+FULLRESYNC回覆,則表示主服務器將與從服務器執行完整重同步。

(4)若是主服務器返回+CONTINUE回覆,則表示部分重同步,從服務器只需等待接收數據便可。

(5)主服務器返回-ERR回覆,則表示主服務器版本低於2.8不識別PSYNC命令從服務器將向主服務器發送SYNC命令完成同步操做。

複製的實現

一、執行SLAVEOF ip port命令,此時從服務器首先將ip與端口保存到服務器狀態的masterhost屬性與masterport屬性裏面,並向客戶端返回「OK」,表示命令已經被接收。

二、創建套接字鏈接

從服務器根據ip與端口建立連向主服務器的套接字,若是套接字鏈接到主服務器,那麼從服務器將爲這個套接字關聯一個 專門用於處理複製工做的文件事件處理器,這個事件處理器負責執行後續複製工做。主服務器在接受從服務器的套接字鏈接後,將爲該套接字建立相應的客戶端狀態,並將從服務器看做一個鏈接到主服務器的客戶端對待,

三、發送PING命令

做用:

(1)雖然與主服務器創建套接字鏈接,但雙方並未使用該套接字進行任何通訊,檢查套接字讀寫是否正常。

(2)檢查主服務器是否可以正常處理命令請求。

發送命令後可能遇到的三種狀況:

(1)超時,在規定的時間限制內從服務器未收到回覆內容,此時從服務器斷線重連。

(2)若是主服務器向從服務器回覆一個錯誤,表示主服務器暫時沒法處理從服務器的命令請求,從服務器斷線重連。

(3)收到正常回復內容,則能夠進行下一步操做。

四、身份驗證(若是從服務器設置了masterauth選項)

從服務器向主服務器發送一條AUTH命令,此時從服務器可能遇到的狀況有:

(1)主服務器沒有設置requirepass選項,而且從服務器沒有設置master選項,那麼從服務器將繼續執行從服務發送的命令,複製操做繼續。

(2)若是從服務器經過AUTH命令發送的密碼與主服務器requirepass設置的密碼相同,那麼主服務器將繼續執行從服務器發送的命令,若是不一樣則主服務器返回一個invalid password錯誤。

(3)若是主服務器設置了requirepass選項,但從服務器沒有設置masterauth選項,那麼主服務器將返回一個NOAUTH選項。另外一方面若是主服務器沒有設置requirepass選項,但服務器設置了masterauth選項,那麼主服務器將返回一個no password is set 錯誤。

五、發送端口信息,從服務器將執行REPLCONF listening-port port命令,向主服務器發送從服務器的監聽端口號,主服務器將端口號保存在對應的客戶端狀態slave_listening_port屬性中。

六、同步

 

七、命令傳播

主服務器將本身執行的寫命令發送給從服務器,從服務器只要一直執行主服務器發來的命令便可。

 

心跳檢測

在命令傳播階段,從服務器默認以每秒一次的頻率向主服務器發送命令:

REPLCONF ACK <replication_offset>

做用:檢測主服務器的網絡鏈接狀態;輔助實現min-slaves選項;檢測命令丟失。

Redis的min-slaves-to-write和min-slaves-max-lag兩個選項防止主服務器在不安全的狀況下執行寫命令。

當從服務器小於min-slaves-to-write或者min-slaves-to-write個數量的服務器延遲lag值都大於等於min-slaves-max-lag時,主服務器將拒絕執行寫命令。

若是由於網絡故障,主服務器傳播給從服務器的寫命令半路丟失,那麼當從服務器向主服務器發送REPLCONF ACK命令時,主服務器將發覺從服務器當前的複製偏移量少於本身的偏移量,主服務器就會根據從服務器提交的複製偏移量,在複製積壓緩衝區裏面找到從服務器缺乏的數據,並將這些數據從新發送給從服務器。

 


 

 

天天學一點,總會有收穫。

 

下一步咱們看下Redis的Sentinel(哨兵)

 

說明:尊重做者知識產權,文中內容參考《Redis設計與實現》,僅在此作學習與你們分享。

 

相關文章
相關標籤/搜索