上一篇寫了Redis復制功能的簡單應用,下面我們看下Redis復制功能的實作程序,下面基本上是理論部分,枯燥乏味,但希望大家能看看,畢竟知識不都是感興趣的.
耐得住寂寞,經得起傭訓,方能守得住繁華 ~.~
舊版復制功能的實作
Redis的復制功能分為同步和命令傳播兩個操作:
1、同步操作用于將從服務器的資料庫狀態更新至主服務器當前所處的資料庫狀態,
2、命令傳播操作則用于在主服務器 的資料庫狀態被修改,導致從服務器的資料庫狀態出現不一致時,讓主服務器的資料庫重新回到一致狀態,
從服務器對主服務器的同步操作需要通過向主服務發送sync命令來完成,以下是sync命令的執行步驟:
(1)從服務器向主服務器發送SYNC命令
(2)收到SYNC命令的主服務器執行BGSAVE命令,在后臺生成一個RDB檔案,并使用一個緩沖區記錄現在開始執行的所有寫命令,
(3)當主服務器的BGSAVE命令執行完畢時,主服務器會BGSAVE命令生成的RDB檔案發送給從服務器,從服務器接收并載入這個RDB檔案,將自己的資料庫狀態更新至主服務器執行BGSAVE命令時的資料庫狀態,
(4)主服務器將記錄在緩沖區的所有寫命令發送給從服務器,從服務器執行這些寫命令,將自己的資料庫狀態更新至主服務器資料庫當前所處的狀態,
命令傳播:當主服務器執行客戶端寫命令時,主服務器的資料庫就有可能被修改,并導致主從不一致,此時主服務器會將自己執行的寫命令發送給從服務器執行,當從服務器執行了相同的寫命令后,主從服務器再次回到一致狀態,
缺陷:
1、初始復制從服務器從來沒有復制過任何主服務器或者從服務器當前要復制的主服務器和上次復制的主服務器不同,
2、斷線后重復制:處于命令傳播階段的主從服務器因為網路原因而中斷了復制,但從服務器通過自動連接從新連上主服務器,并繼續復制,
新版復制功能的實作(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命令完成同步操作,
復制的實作
1、執行SLAVEOF ip port命令,此時從服務器首先將ip與埠保存到服務器狀態的masterhost屬性與masterport屬性里面,并向客戶端回傳“OK”,表示命令已經被接收,
2、建立套接字連接
從服務器根據ip與埠創建連向主服務器的套接字,如果套接字連接到主服務器,那么從服務器將為這個套接字關聯一個 專門用于處理復制作業的檔案事件處理器,這個事件處理器負責執行后續復制作業,主服務器在接受從服務器的套接字連接后,將為該套接字創建相應的客戶端狀態,并將從服務器看作一個連接到主服務器的客戶端對待,
3、發送PING命令
作用:
(1)雖然與主服務器建立套接字連接,但雙方并未使用該套接字進行任何通信,檢查套接字讀寫是否正常,
(2)檢查主服務器是否能夠正常處理命令請求,
發送命令后可能遇到的三種情況:
(1)超時,在規定的時間限制內從服務器未收到回復內容,此時從服務器斷線重連,
(2)如果主服務器向從服務器回復一個錯誤,表示主服務器暫時無法處理從服務器的命令請求,從服務器斷線重連,
(3)收到正常回復內容,則可以進行下一步操作,
4、身份驗證(如果從服務器設定了masterauth選項)
從服務器向主服務器發送一條AUTH命令,此時從服務器可能遇到的情況有:
(1)主服務器沒有設定requirepass選項,并且從服務器沒有設定master選項,那么從服務器將繼續執行從服務發送的命令,復制操作繼續,
(2)如果從服務器通過AUTH命令發送的密碼與主服務器requirepass設定的密碼相同,那么主服務器將繼續執行從服務器發送的命令,如果不同則主服務器回傳一個invalid password錯誤,
(3)如果主服務器設定了requirepass選項,但從服務器沒有設定masterauth選項,那么主服務器將回傳一個NOAUTH選項,另一方面如果主服務器沒有設定requirepass選項,但服務器設定了masterauth選項,那么主服務器將回傳一個no password is set 錯誤,
5、發送埠資訊,從服務器將執行REPLCONF listening-port port命令,向主服務器發送從服務器的監聽埠號,主服務器將埠號保存在對應的客戶端狀態slave_listening_port屬性中,
6、同步

7、命令傳播
主服務器將自己執行的寫命令發送給從服務器,從服務器只要一直執行主服務器發來的命令即可,
心跳檢測
在命令傳播階段,從服務器默認以每秒一次的頻率向主服務器發送命令:
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設計與實作》,僅在此做學習與大家分享,

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/2469.html
標籤:NoSQL
上一篇:Redis 哨兵機制
