天天看點

06 資料同步:主從庫如何實作資料一緻

本篇重點

主從庫同步原理、如何應對主從庫間網絡斷連風險
主從庫同步:全量複制、基于長連接配接的指令傳播、增量複制——應對主從庫間的網絡斷連

背景

若Redis隻有一個執行個體運作,當該執行個體服務當機後,當機這段時間内Redis無法為新來的資料請求提供服務。

Redis采取的解決方案是——增加副本備援量,即将一份資料同時儲存在多個執行個體上——Redis主從庫模式

多執行個體儲存同一份資料,需要考慮的問題:

  • 副本間的資料如何保持一緻?——資料同步
  • 資料讀寫操作可以發給所有執行個體嗎?——資料讀寫

前言

Redis高可靠性的保證
  • 資料盡量少丢失——持久化存儲(AOF/RDB)
  • 服務盡量少中斷——主從庫(本質是增加副本備援量)

Redis主從庫模式

  • Redis主從庫模式:保證資料副本一緻性,且主從庫 “讀寫分離”
  • 讀寫分離:
    • 讀操作:主從庫都可接收
    • 寫操作:主庫接收并執行,然後由主庫将寫操作同步給從庫
    • 主從庫讀寫分離
      06 資料同步:主從庫如何實作資料一緻
  • 主從庫同步的三個問題:
    • 實作原理——如何完成主從庫
    • 主庫資料是一次性傳給從庫,還是分批同步?
    • 主從庫間網絡斷連了,資料還能保持一緻嗎?

1. 主從庫第一次同步

  • replicaof

    指令——建立主從庫關系[1]
    • 某Redis執行個體執行:

      replicaof 主庫IP 主庫port

    • 該執行個體與主庫建立主從庫關系,成為主庫的從庫
  • 主從庫第一次同步的三個階段(某執行個體第一次執行

    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核心技術與實戰》
  1. Redis5.0前使用

    slaveof

    指令 ↩︎

繼續閱讀