如果看完這篇還不懂Redis主從,請來錘我。

redis主從複製是redis相關知識中比較常見的知識,也是比較重要的知識點,本片文章主要主要來寫一下redis主從複製的原理實現(全量複製及部分複製),以及它們之間的檢測機制,還有一些實際運用中會出現的問題。


何爲主從複製

主從複製,即有兩個角色,主節點和從節點,數據從主節點複製到從節點,且不能逆向複製。



主從複製整體步驟

通過向從節點發送 SLAVEOF 命令,可以讓主從複製開始工作,以下爲具體步驟。


1. 設置主節點地址和端口

SLAVEOF 127.0.0.1 6379 此命令指定了主節點的地址及端口,表示從節點要從127.0.0.1:6379來複制數據


2. 建立套接字連接

在SLAVEOF 命令執行之後,從服務器根據設置的ip及port,會創建一個連向主節點的套接字連接,如果連接成功,那麼從服務器將爲這個套接字關聯一個專門用於處理文件事件處理器,負責以後的複製工作,如接收RDB文件,以及接收主節點傳輸過來的寫命令。


3. 發送PING命令

從節點成爲主節點的客戶端之後,首先會發送一條PING命令,此時的PING命令有兩個作用:

    1. 主從節點首次通信,檢查該套接字讀寫狀態是否正常。
    1. 檢查主節點能否正常處理命令請求。

從節點在發送PING命令之後,將會遇到一下三種情況:

    1. 從節點在規定時間內沒有收到命令回覆,表示主從節點的網絡應該不太穩定,不能繼續後續的複製步驟,應斷開並重新連接主節點的套接字。
    1. 從節點收到主節點返回的錯誤信息,表示主節點暫時無法處理從服務器的命令請求,不能繼續執行後續的複製工作,應斷開並重新連接主節點的套接字。
    1. 從節點收到主節點返回的PONG,表示主從之間的網絡正常,且主節點可以處理從節點的命令請求,可以繼續後續的複製工作。

4. 身份驗證

從節點收到主節點的PONG回覆之後,下一步就該確認是否進行身份驗證

    1. 如果從節點設置了masterauth,則進行身份驗證
    1. 如果從節點沒有設置masterauth,則不進行身份驗證

從節點在身份驗證階段可能遇見以下幾種情況:

  1. 主服務器沒有設置requirepass選擇,從節點沒有設置masterpass,複製工作可以繼續進行
  2. 從節點通過AUTH 發送的命令和主節點配置requirepass 設置的密碼相同,則複製工作可以進行。如果不同,主節點將返回一個invalid password錯誤
  3. 如果主節點設置了requirepass,從節點沒有設置masterauth,那麼主節點將返回一個NOAUTH錯誤。相反,如果主節點沒有設置requirepass,從節點設置了masterauth,那麼主節點將返回no password is set

所有的錯誤情況都會使從節點終止複製工作,並從創建套接字開始重新執行復制,直到身份驗證通過,或者從節點放棄複製爲止。


5. 發送端口信息

在身份驗證之後,從節點將執行命令REPLCONF listening-port port,主節點將把端口信息記錄在自己的客戶端狀態信息中

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=137741805,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=137741805,lag=0
master_repl_offset:137741805
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:136693230
repl_backlog_histlen:1048576

6. 同步

6.1 舊版 (v2.8以前) 同步的實現

舊版的同步功能需要從節點向主節點發送sync命令來完成,步驟如下:

1.從節點向主節點發送SYNC命令

2.收到SYNC命令的主節點執行BGSAVE命令,在後臺生成一個RDB文件,並使用一個緩存區記錄從現在開始執行的命令

3.當主節點的BGSAVE命令執行完畢時,主節點會把BGSAVE生成的RDB文件傳送給從節點,然後從節點接收到這個RDB文件,將自己的數據庫狀態更新至此RDB文件的狀態

4.主節點將記錄在緩衝區裏所有的寫命令發送給從節點,從節點執行這些命令後,保證此時主從的數據庫狀態相同

過程如圖所示:

舊版同步的缺陷

同步可以分爲兩個情況,第一是初次同步,第二是斷線後同步,這個缺陷就是在斷線後同步時,繼續一遍上面的步驟,雖然這個同步的數據沒有問題,但是其實很多數據是沒有必要複製的。

耗費資源的SYNC命令
執行SYNC命令主從節點需要做一下事情

  1. 主節點執行BGSAVE命令在後臺生成RDB文件,會耗費主節點大量的CPU、內存和磁盤IO等資源
  2. 主節點需要將RDB文件發送給從節點,這個操作會消耗主節點大量的網絡資源。
  3. 從節點接收並載入RDB文件,且載入期間會阻塞命令請求

6.2 新版 (v2.8以後)同步的實現。

在此,從節點會使用PSYNC代替SYNC命令,從節點會向主節點發送PSYNC命令,執行同步操作,並將自己的數據庫狀態更新至主節點數據庫所處的狀態。

PSYNC命令分兩種模式,一個是完整同步操作,一個是部分同步模式。

  • 完整同步模式:通過讓主節點創建併發送RDB文件,以及向從節點發送保存在緩衝區中的寫命令來進行同步。
  • 部分同步模式:藉助複製積壓緩衝區以及複製偏移量來進行部分同步。

部分同步的功能主要由下面三個部分構成:

  • 主節點的複製偏移量及從節點的複製偏移量
  • 主節點的複製積壓緩衝區
  • 節點運行id
6.1.1 複製偏移量

執行復制的雙方,主從節點都分別維護這一個複製偏移量
主節點每次向從節點傳播N個字節的數據時,就會將自己的複製偏移量加N。同理,從節點每次收到主節點傳播來的N個字節的數據時,也會將自己的複製偏移量加N

通過對比主從節點的複製偏移量,可以確定主從節點是否處於一致狀態

6.1.2 複製積壓緩衝區

如上圖所示,假設正在複製的從節點A斷線了,主節點傳過來的字節數據收不到了,此時從節點A的偏移量(offset)和主節點的不一致了,過了一段時間,從節點A又成功連接至主節點,接下來它是怎麼樣和主節點數據保持一致呢,這就要說到複製積壓緩衝區了。

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

當主節點向從節點進行命令傳播的時候,它不僅會把命令發送給所有的從節點,還會將命令入隊到複製積壓緩衝區中,如下圖所示。

那麼複製積壓緩衝區裏面到底是什麼按照格式存儲的呢,它會爲每個字節記錄相應的偏移量,其構造如下圖所示:

複製積壓緩衝區大致就是這樣了,下面來說一下當從節點A重新連上主節點後的是什麼樣的情況。

  • 從節點會通過PSYNC命令將自己的偏移量offset發送給主節點,如果偏移量之後的之後的數據還存在複製積壓緩衝區中,主節點將對從節點進行部分同步
  • 相反,如果偏移量之後的數據已經不在複製積壓緩衝區中,則進行完整同步
6.1.3 服務器運行id

除了複製偏移量和複製積壓緩衝區之外,部分不同還需要服務器運行id

  • 每個redis服務器,不論主從,都會有一個自己的運行id
  • 每個id在服務啓動時自動生成,由40個隨機的16進制字符組成

當從節點對主節點進行初次複製時,主節點會將自己的運行id傳給從節點,從節點會把這個id保存起來。當從節點斷線並重新連接上一個主節點時,從節點會向當前的主節點發送之前保存的運行id

  • 如果保存的運行id和當前主節點id相同,則說明和斷線之前連接的是一個主節點,可以嘗試部分同步操作
  • 如果運行id和當前節點不同,和斷線之前連接的不是一個主節點,需要執行完整同步操作

7. 命令傳播

當完成同步之後,主從節點進入命令傳播階段,此時主節點只需要將自己的寫命令發送給客戶端,從節點接收並執行主節點發送過來的寫命令即可。


喜歡我寫的東西的朋友可以關注一下我的公衆號,上面有我的學習資源以及一些其他福利。:Devops部落

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