本篇重點
主從庫同步原理、如何應對主從庫間網絡斷連風險
主從庫同步:全量複制、基于長連接配接的指令傳播、增量複制——應對主從庫間的網絡斷連
背景
若Redis隻有一個執行個體運作,當該執行個體服務當機後,當機這段時間内Redis無法為新來的資料請求提供服務。
Redis采取的解決方案是——增加副本備援量,即将一份資料同時儲存在多個執行個體上——Redis主從庫模式
多執行個體儲存同一份資料,需要考慮的問題:
- 副本間的資料如何保持一緻?——資料同步
- 資料讀寫操作可以發給所有執行個體嗎?——資料讀寫
前言
Redis高可靠性的保證
- 資料盡量少丢失——持久化存儲(AOF/RDB)
- 服務盡量少中斷——主從庫(本質是增加副本備援量)
Redis主從庫模式
- Redis主從庫模式:保證資料副本一緻性,且主從庫 “讀寫分離”
- 讀寫分離:
- 讀操作:主從庫都可接收
- 寫操作:主庫接收并執行,然後由主庫将寫操作同步給從庫
- 主從庫讀寫分離
06 資料同步:主從庫如何實作資料一緻
- 主從庫同步的三個問題:
- 實作原理——如何完成主從庫
- 主庫資料是一次性傳給從庫,還是分批同步?
- 主從庫間網絡斷連了,資料還能保持一緻嗎?
1. 主從庫第一次同步
-
指令——建立主從庫關系[1]replicaof
- 某Redis執行個體執行:
replicaof 主庫IP 主庫port
- 該執行個體與主庫建立主從庫關系,成為主庫的從庫
- 某Redis執行個體執行:
- 主從庫第一次同步的三個階段(某執行個體第一次執行
與主庫建立連接配接)replicaof
- 建立連接配接,協商同步
- 從庫->主庫:psync
- 主庫->從庫:FULLRESYNC
- 資料同步
- 主庫->從庫:RDB快照
- 從庫:清楚舊有資料,加載RDB
- 主庫在資料同步中,執行完RDB後,正常接收 & 執行的寫操作會被寫入 replication buffer 中
- 同步資料同步期間到來的寫操作——replication buffer
- 主庫->從庫:replication buffer
- 從庫:重新執行replication buffer中的操作
- 建立連接配接,協商同步
- Redis第一次主從同步流程
06 資料同步:主從庫如何實作資料一緻 - 指令及參數解釋:
-
指令形式:psync
psync runID offset
-
runID:Redis執行個體ID,首次連接配接主庫ID未知,傳?
-
offset:複制進度,第一次複制傳-1
-
FULLRESYNC: 全量複制,第一次建立連接配接采用全量複制
-
Q:主從庫同步中,主庫執行RDB快照時,需要fork bgsave子程序,若從庫數量很多,則主庫fork的壓力就會增加,如何應對這種問題?緩解主庫壓力?
A:主從級聯模式——“主—從—從”,在從庫間建立“主從”關系,分擔主庫全量RDB的壓力
2. 主從級聯模式:分擔全量複制時的主庫壓力
- “主—從—從”模式:選擇一個從庫(記憶體配置較高),級聯其他從庫(replicaof)
3. 基于長連接配接的指令傳播——避免頻繁建立連接配接
- 主從庫建立網絡連接配接後,此時主從庫間已經完成了一次全量複制,後續Redis執行個體會維護這個網絡連接配接,在這個網絡連接配接上進行 “寫操作同步”
- “主—從—從”模式
06 資料同步:主從庫如何實作資料一緻
4. 增量複制——主從網絡斷連後的解決方案
增量複制——僅同步斷連期間主庫收到的指令
repl_backlog_buffer——環形緩沖區,存儲主庫收到的寫指令——記錄主/從的寫/讀進度,通過offset
- master_repl_offset:主庫寫offset,遞增值
- slave_repl_offset: 從庫讀offset,遞增值
- 主從庫連接配接期間,master_repl_offset == slave_repl_offset
- 主從庫斷連後,master_repl_offset >= slave_repl_offset
Redis增量複制流程
- 斷連期間
- 主庫->replication buffer: 存儲寫指令(用于寫操作同步)
- 主庫->repl_backlog_buffer: 存儲寫指令
- 主庫:記錄 master_repl_offset
- 連接配接恢複時
- 從庫->主庫:
psync 主庫runID slave_repl_offset
- 主庫->從庫:slave_repl_offset之後的寫指令(全量/增量)
- 從庫:執行這些寫指令
- 從庫->主庫:
- Redis增量複制流程
06 資料同步:主從庫如何實作資料一緻
Q: 主庫寫入速度快,從庫讀取慢,導緻未讀的指令被新寫的指令覆寫,引起的主從庫資料不一緻問題如何預防?
A:
- 調整 repl_backlog_size 大小,通常 = 緩沖空間大小*2
- 或采用切片叢集分擔單個主庫的請求壓力(将寫請求分散到叢集中)
Q: 主從斷連時間過長,導緻slave_repl_offset上的未讀資料已經被新寫入操作覆寫(同上一個問題),如何資料同步?
A: 主庫采用全量複制
- 主庫判斷被覆寫—— master_repl_offset - slave_repl_offset > repl_backlog_size (個人猜想)
- 若上式成立,則執行全量複制,否則增量複制
Q: 本篇讨論的都是“主庫如何同步資料給從庫”、“斷連恢複後主庫如何同步斷連期間的資料給從庫”的問題,那麼當主庫挂了,Redis如何對外提供服務?此時從庫能起到什麼樣的作用?——主從庫模式的重要功能——服務盡量少中斷
A: Redis的哨兵機制[連結]
圖檔來源于極客時間專欄《Redis核心技術與實戰》
- Redis5.0前使用
指令 ↩︎slaveof