Redis主從複製原理剖析
生產環境中,為保證Redis快取系統的高可用性,對於Redis叢集,一般都會採用主從架構來實現讀寫分離。
那麼主從架構下,主節點和從節點間,資料是如何進行復制和同步,中間是一個什麼樣的流程,通過本文,想跟眾博友和同行一起討論。
首先看一個圖。
上圖展示了Slave節點第一次連線主節點和短暫斷開後再次連線主節點的情況下,資料複製的流程。
- 當從節點啟動後,會根據自身配置檔案中slave of配置的內容,得到主節點的IP和埠。
- 從節點向主節點傳送一個psync命令(如果主節點設定了祕鑰等安全資訊,則需帶上主節點的安全資訊),看看主節點是否能夠連線,如果主節點成功連線,則返回主節點的run id、offset資訊,同時觸發全量複製(Full Resynchronizztion)。
- 主節點fork一個子程式,執行bgsave命令,生成一個rdb快照。通過主節點中repl-diskless-sync、repl-diskless-sync-delay兩個配置,來選擇是否開啟無磁碟化的複製。
-
repl-diskless-sync預設為no,即不開啟無磁碟化配置,那麼在全量複製開始時,主節點fork出的子程式將rdb快照寫入磁碟。然後檔案通過父程式傳輸給排隊執行全量複製的所有Slave節點。
-
repl-diskless-sync如果設定為yes,即開啟無磁碟化複製,無磁碟化複製指的就是主程式fork子程式生成rdb快照檔案時,該檔案在主節點上不落盤,而是通過與Slave節點建立的socket連線直接將檔案推送給Slave節點。
-
repl-diskless-sync如果設定為yes,此時為了讓同一份rdb檔案能夠同時提供給更多的Slave節點,需配合repl-diskless-sync-delay這個配置一起使用。repl-diskless-sync-delay指的是在建立子程式生成rdb快照之前等待一段時間(如5秒),期望更多的子節點與主節點之間建立socket連線,生成rdb檔案之後可以一次性複製給多個子節點。
在子程式生成rdb檔案並與從節點間程式rdb檔案資料複製的過程中,新寫入的資料,Redis將會儲存到緩衝區。緩衝區大小可以通過client-output-buffer-limit這個配置來設定。如:
client-output-buffer-limit slave 256MB 64MB 60
指的就是在rdb快照複製過程中,如果緩衝區資料超過256M,
或者持續60秒超過64M,則同步失敗。
- Redis子程式通過與從節點建立的Socket連線,直接傳送rdb快照給Slave節點。
- Slave節點收到rdb快照後落盤,然後進行載入。
- 從節點完成rdb快照載入之後,Redis傳送新寫入到緩衝區的資料寫命令給從節點,執行增量複製,保證主節點和從節點的資料一致。
- 後續每寫入一條資料,主節點都會非同步將該資料的寫命令傳送給從節點。
- 因為某些原因,從節點與主節點短暫斷開連線,導致主從節點資料不一致。
- 當slave連線到master,會執行
PSYNC <runid> <offset>
傳送記錄舊的master的runid(replication ID)和偏移量offset,這樣master能夠只傳送slave所缺的增量部分。但是如果master的複製積壓快取區沒有足夠的命令記錄,或者slave傳的runid(replication ID)不對,就會進行完整重同步,即slave會獲得一個完整的資料集副本。
-
部分資料同步,需要的幾個參考值解釋如下:
-
run id(replication ID),每個Redis服務啟動時,都會生成一個run id,從節點與主節點建立連線後,主節點會將自己的run id同步給從節點。
-
offset:複製偏移量,主節點和從節點各自維護了一個複製偏移量,記錄傳輸的位元組數。當主節點向從節點傳送N個位元組資料時,主節點的offset增加N,從節點收到主節點傳來的N個位元組資料時,從節點的offset增加N。
-
replication backlog buffer,複製積壓緩衝區。是一個固定長度的FIFO佇列,大小由配置引數repl-backlog-size指定,預設大小1MB。需要注意的是該緩衝區由master維護並且有且只有一個,所有slave共享此緩衝區,其作用在於備份最近主庫傳送給從庫的資料。
- 主節點判斷,重新建立連線的從節點,符合部分資料同步的條件,將複製積壓緩衝區的資料寫命令,傳送給從節點,完成資料複製。
小結:
從上述的整個流程我們不難看出,使用Redis主從架構,基於其資料複製的規則和原理,為了資料的安全,我們必須開啟主節點的持久化功能,並且在資料量極大的情況下,一定要做好主節點資料備份的策略,避免因為主節點當機重啟而造成大量資料丟失,最後造成不可挽回損失。
因為如果主節點不做資料持久化,主節點當機重啟後,由於run id重啟後發生了變化,所有從節點重新與主節點建立連線後,都會全量同步主節點的資料,但是主節點沒有持久化資料,從節點也就全部都會被清空。
即使使用Redis哨兵,可以在主節點當機後將從節點提升為主節點,但是在某些極端情況下,假設你的伺服器允許自動重啟Redis程式,Redis主節點當機到重啟的這個短暫時間內,Redis哨兵還未來得及發現主節點下線,也會造成資料丟失。
相關文章
- CAS實現單點登入SSO執行原理探究
- Linux下安裝Redis
- 93面試常問:Redis 記憶體滿了怎麼辦?
- 《.NET 5.0 背鍋案》第7集-大結局:捉拿真凶 StackExchange.Redis.Extensions 歸案
- flinkSql join redis的hash結構維表簡單實現
- Redis分散式鎖的使用與實現原理
- 編譯原理讀書筆記
- Redis5 的新特性 Redis Stream
- 【深度學習原理第4篇】卷積神經網路詳解(CNN)
- 99面試常問:中高階開發面試必問的Redis,看這篇就夠了!
- 蟻劍原理與魔改
- Java動態代理—框架中的應用場景和基本原理
- React基礎與原理實現
- Python 字典實現原理
- 六、Alibaba sentinel之限流原理分析
- 現代作業系統-原理與實現【讀書筆記】
- Android10_原理機制系列_Activity視窗新增到WMS過程
- 檔案上傳踩坑記及檔案清理原理探究
- redis原始碼學習之slowlog
- 計算機組成原理期末考試題