redis 主從復制詳解


引言

我們之前操作 Redis 都是單機版,但是實際應用中沒人使用單機版,都是搭建集群的方式。這篇文章要介紹的主從復制,是指將一台 Redis 服務器的數據,復制到其他 Redis 服務器,我們將前者稱為主節點 master,將后者稱為從節點 slave(replica)。在這個過程中,數據的復制是單向的,即只能從主節點到從節點。並且從節點只能讀數據,不能寫數據,實現讀寫分離。

image-20210523232751628

  • 一個主節點可以有多個從節點,一個從節點只能有一個主節點。所有的服務器默認都是主節點。
  • 從節點下面還可以有從節點,形成一個圖的結構

主從復制的優點

  1. 數據冗余:主從復制實現了數據的熱備份,是持久化之外的一種數據冗余方式。
  2. 故障恢復:當主節點出現問題時,可以由從節點提供服務,實現快速的故障恢復;實際上是一種服務的冗余。
  3. 負載均衡:在主從復制的基礎上,配合讀寫分離,寫數據時應用連接主節點,讀數據時應用連接從節點,分擔服務器負載;尤其是在寫少讀多的場景下,通過多個從節點分擔讀負載,可以大大提高 Redis 服務器的並發量。
  4. 高可用基礎:主從復制是哨兵模式和集群能夠實施的基礎。

開啟主從復制

主從復制的前提就是多個 Redis 服務器,因此要多個配置文件。

image-20210524103338585

開啟主從復制的方式有兩種:

  • 配置配置文件

    從服務器配置master節點

    # 主節點ip port
    # replicaof <masterip> <masterport>
    # 主節點的認證密碼(可選)
    # masterauth <master-password>
    
  • 顯示命令開啟

    客戶端使用該命令slaveof [ip] [port]

    INFO REPLLICATION命令可查看節點信息

    image-20210524104322704

    image-20210524104335218

主從復制的具體實現

主從復制的實現可以分為三個階段:建立連接、數據同步、命令傳播

1. 建立連接

  • 發送 slaveof 異步命令

  • 建立 socket 連接

    image-20210524140639712

    連接成功后從節點會為該 socket 建立一個專門處理復制工作的文件事件處理器,負責后續的復制工作,如接收 RDB 文件、接收命令傳播等;

  • 發送 ping 命令

    從節點成為主節點的客戶端之后,發送 ping 命令進行首次請求,目的是檢查 socket 連接是否可用,以及主節點當前是否能夠處理請求

  • 身份驗證

    取決於從節點是否設置 masterauth 選項,而這個又取決於主節點是否設置 requirepass

  • 發送從節點端口信息

2. 數據同步

連接建立完成后,要進行主從數據庫的數據同步,這一步也可以看作從節點中數據的初始化。數據同步有舊版和新版兩種。我們先來看看舊版 Redis 怎么實現數據同步的

舊版同步

舊版同步使用的命令是 sync,同步方式是全量復制。以下是sync命令的執行步驟:

  • 從服務器向主服務器發送 sync 命令
  • 主服務器收到后執行 BGSAVE 的rgb持久化命令,生成一個RDB文件。並用一個緩沖區記錄生成rgb文件期間執行的所有寫命令。
  • 主服務器將 rgb 文件發送給從服務器,從服務器載入整個 rgb 文件,同步數據庫狀態至執行 BGSAVE 時主服務的狀態
  • 主服務器將記錄在緩沖區的寫命令發送給從服務器。至此從服務和主服務數據庫狀態達到一致。

舊版同步功能的缺陷:

  • 斷線后重連需要再次發送 sync 同步命令,主服務再次生成 rgb 文件,從服務器載入恢復數據庫狀態。簡單來說就是斷線后又要全量復制,但其實沒有必要,我們只需要同步斷線后到重新連接期間主服務器變化的數據即可。

    並且,sync是一個非常耗費資源的操作,因此舊版同步是非常低效的。

新版同步

新版同步使用的命令是 psync ,同步方式是增量復制

psync 有完成重同步和部分重同步兩種模式。完整重同步其實就是sync,主要用於處理初次服務的情況。部分重同步主要用於處理斷線后重連的情況。部分重同步不需要重新生成、傳送和載入整個rdb文件,只需要將從服務器缺少的寫命令發送給從服務器執行即可。完美的解決了舊版同步效率低下的問題。

下面我們就來看看他是如何實現的?首先要了解幾個概念

  • 主節點和從節點的復制偏移量

    主節點和從節點會各自維護一個復制偏移量 ( offset ),代表的是主節點向從節點傳遞的字節數。主節點每次向從節點傳播 N 個字節數據時,主節點的 offset 增加 N;同理,當從節點每次收到主節點傳來的 N 個字節數據時,從節點的 offset 增加 N。通過比較主節點和從節點的 offset 可以判斷數據庫狀態是否一致,如果兩者的 offset 相同,則一致,否則不一致;也可以根據兩者的 offset 找出從節點缺少的數據。

    image-20210524135534199

  • 主節點的復制積壓緩沖區

    主節點維護的一個固定長度的先進先出 ( FIFO) 隊列,默認大小是 1MB。當主節點開始有從節點時,主節點創建復制積壓緩沖區,其作用是備份主節點最近發送給從節點的數據。保存的數據有兩方面:

    • 最近傳播的寫命令。為什么最近呢?因為隊列長度固定,老的命令會被新的取代
    • 隊列中每個字節對應的復制偏移量

    當從服務器重新連接上主機時,會通過 psync 命令把自己的offset發給主節點

    • 如果offset之后的數據全部在隊列中,執行部分重同步(增量復制)
    • 如果offset之后的數據不全在隊列中,執行完整重同步(全量復制)
  • 服務器的運行ID

    每個redis服務器都有自己的運行ID,在啟動時自動生成,由40個隨機的十六進制字符組成

    當從節點對主節點進行初次復制時,主節點會把自己的運行ID發給從節點,從節點保存並在斷線重連上主節點時把次ID發送給主節點:

    • 如果此ID和主節點當前連接的ID一致,說明是同一個狀態,可以進行增量復制
    • 如果不同,只能進行全量復制

總結:psync的執行流程:

img

命令傳播

數據同步階段完成后,主從節點進入命令傳播階段;在這個階段主節點將自己執行的寫命令發送給從節點,從節點接收命令並執行,從而保證主從節點數據的一致性。

這個階段沒啥可說的,就是把主節點執行的寫命令發給從節點,讓它們也執行一次,保證主從一致性

心跳檢測

在命令傳播階段,從服務器默認會以每秒一次的頻率向主服務器發送replconf ACK <replication_offset>,其中replication_offset是它當前的復制偏移量。心跳檢測的目的有以下三個:

  • 檢測主從服務器的網絡連接狀態

    如果主服務器超過一秒沒有收到從服務的該命令,那么主服務器就知道主從連接出現問題了

    image-20210524141936758

  • 輔助實現min-slaves

    主服務我們可以配置以下兩個參數來防止不安全寫命令傳播,如果從節點小於3或者lag大於10,主服務器都會拒絕執行寫命令

    # 從節點的最小個數
    # min-replicas-to-write 3
    # 從節點lag的最大值
    # min-replicas-max-lag 10
    
  • 檢測命令丟失

    上面說過心跳檢測命令還發送了從節點自身保存的offset。主節點會與自己的 offset 進行對比,如果從節點數據缺失(如網絡丟包),主節點會找到缺失的數據,並把這些數據重新推送給服務器(這里也會利用復制積壓緩沖區)。

    參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM