Redis 主從複製架構

1. 單機版的侷限

       單機版的侷限性在哪裏?

       如果Redis所在的實例宕機,那麼此時即不支持讀也不支持寫,這便是單機版存在的問題,可用性和併發性都是非常有限的。

       爲解決上述的問題,從而引出了主從複製架構。

2. 主從複製架構分析

       主從架構的示意圖如下

在這裏插入圖片描述
       客戶端所有的寫操作都是通過 Master 實例來完成,所有的讀操作都是通過Slave來完成的,從而實現讀寫分離。

       優點

  1. 可用性提高。當Master宕機後,依然可以對Slave讀操作。當一臺Slave宕機,依然可以讀其他Slave進行讀操作。
  2. 併發性提高。更準確的是對讀的併發性有所提高,可以對多臺的slave進行讀取,同時,當業務量劇增時,隨時可以增加新的Slave

       缺點

  1. 可用性有限:當Master宕機後,此時寫操作都失敗,直到實例重啓。
  2. 數據同步問題:數據從Master同步到Slave時,帶來的數據不一致性問題,該問題在分佈式鎖的環境下尤爲明顯。

3. 主從複製原理

       slave實例可以通過執行SLAVEOF或設置slaveof <masterip> <masterport> 去複製master服務器。

3.1 舊版複製功能的實現

       Redis 2.8 版本以前複製的實現原理如下:

       Redis的複製功能分爲同步sync和命令傳播command propagate兩個操作:

  • 同步:用於將從服務器的數據庫狀態更新至主服務器當前時刻數據庫狀態一致
  • 命令傳播:用於主服務器的數據庫狀態被更改後,讓主從數據庫狀態一致

3.1.1 同步

       從服務器發送SLAVEOF命令後,首先會執行同步操作,從服務器通過發送SYNC命令來完成,SYNC命令的執行步驟:

  • 從服務器向主服務器發送 SYNC 命令。

  • 主服務器收到 SYNC 命令後執行 BGSAVE 命令,在後臺生成一個 RDB 文件,並使用緩衝區記錄從現在以後的所有寫命令(防止生成RDB文件的同時,有新命令沒有寫入RDB文件中)。

  • 主服務器將RDB文件發送給從服務器,從服務器載入該RDB文件。

  • 主服務器將緩衝區裏面的命令發送給從服務器,從服務器執行這些寫命令,此時主從數據相互一致。

在這裏插入圖片描述

3.1.2 命令傳播

       同步操作完成後,主從實例便處於一致性狀態,但是當有新的寫命令寫入到主實例,此時便又不一致了。

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
       可見,通過命令傳播可以使主從重新處於一致性狀態。

3.1.3 舊版複製的缺陷

       在從服務器第一次連接主服務器時,會進行RDB的全量載入。但是由於網絡波動,導致主從斷開連接,當從服務器重新連接後,便又會重新發送SYNC命令,進行RDB的全量載入。如果1分鐘內掉線三次,則會進行三次全量複製,可是1分鐘內,Master可能並不會新增很多數據,主從之間的數據差異性並不是很大,所以該方式很浪費資源。

3.2 新版複製功能的實現

       爲了解決主從掉線後的複製權限,Redis 2.8使用PSYN代替SYNC執行同步操作。

       PSYNC具有完整重同步和部分重同步兩種模式。

  • 完整重同步:同 SYNC 命令的執行步驟一樣

  • 部分重同步:用於處理斷線後重複製情況,主服務器可以將主從服務器連接斷開期間執行的寫命令發送給從服務器,從服務器只要接收並執行這些寫命令,就可以將數據庫更新至主服務器當前所處狀態。

3.3 部分重同步的實現

       部分重同步功能由以下三個部分構成:

  • 主服務器的複製偏移量(replication offset)和從服務器的複製偏移量
  • 主服務器的複製積壓緩衝區(replication backlog)
  • 服務器的與運行ID(run ID)

3.3.1 複製偏移量

       主服務器和從服務器都維護一個複製偏移量。

  • 主服務器每次向從服務器傳播N個字節的數據時,就將自己的複製偏移量的值加上N。
  • 從服務器每次收到主服務器傳播來的N個字節的數據個給從服務器時,就將自己的複製偏移量的值加上N。

在這裏插入圖片描述

       通過對比offset的值,可以明顯知道兩者是否處於一致性狀態。

在這裏插入圖片描述
       當處於不一致狀態時,便需要恢復A丟失的數據,其是通過複製積壓緩衝區實現的。

3.3.2 複製積壓緩衝區

       複製積壓緩衝區是主服務器維護的一個固定長度先進先出的==隊列==,默認大小爲 1MB。

       當主服務器進行命令傳播時,不僅會將命令發送給所有從服務器,還會將寫命令入隊到複製積壓緩衝區

在這裏插入圖片描述
       複製積壓緩衝區會爲隊列中的每個字節記錄相應的複製偏移量

在這裏插入圖片描述

       當從服務器重新連接上主服務器時,會通過 PSYNC 命令將自己的複製偏移量 offset 發送給主服務器,主服務器根據這個複製偏移量來決定對從服務器執行何種同步操作:

  • 如果 offset 偏移量之後的數據仍然存在於複製積壓緩衝區,那麼主服務器採用部分重同步。
  • 否則,採用完整重同步(因爲找不到寫命令,只能進行全量複製,所以可以更改緩衝區的大小,使命令被保存的時間更久,這樣就可以進行增量複製)。

3.3.3 服務器運行 ID

  • 每個 Redis 服務器都有自己的運行ID
  • 運行ID由服務器啓動自動生成,由 40 個隨機的 16 進制字符組成

       當從服務器對主服務器進行初次複製時,主服務將自己的運行 ID 傳送給從服務器,從服務器會將這個運行 ID保存起來。

       當從服務器斷線重連上一個主服務器時,從服務器會向主從器發送之前保存的運行ID

       如果運行ID與主服務器的運行ID相同,主服務器可以繼續嘗試執行部分重同步。

       否則,說明主服務器不再是之前的主服務器,需要進行完整重同步操作。

       當一個主服務器宕機後,那麼哨兵系統會選擇一個從服務器作爲主服務器,此時運行ID便不一致了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章