iT邦幫忙

2026 iThome 鐵人賽

DAY 26
0
Software Development

手刻 Redis:用 Go 從零打造高效能高併發的記憶體資料庫系列 第 26

Day 26:Redis 主從複製(Replication)原理解析與 SYNC 協定

  • 分享至 

  • xImage
  •  

單機跑久了總會遇到機器掛掉的時候,就算有 AOF 跟 RDB,重開機還是有一段時間不能服務。加上單機讀寫效能總是有天花板。

為了解決這些問題,Redis 提供了主從複製(Master-Slave Replication)

今天先拆主從複製的流程,尤其是第一次同步時會用到的 SYNC 協定。


主從複製的架構與運作流程

Redis 主從複製大致分成兩段:第一次把資料整包同步過去的全量同步(Full Resynchronization),以及後續持續追寫入的增量同步(Incremental Propagation)

全量同步(Full Resynchronization)
  1. Slave 執行 SLAVEOF host port
  2. Slave → Master:建立 TCP 連線並發送 PING
  3. Master → Slave:回應 PONG(握手成功)
  4. Slave → Master:發送 SYNC 命令
  5. Master:生成當前記憶體的 RDB 快照
  6. Master → Slave:傳送 RDB 二進位數據包
  7. Slave:清空舊數據,加載 RDB 檔案恢復狀態

增量同步(Incremental Propagation,Loop)
  8. Master:開始收集所有後續寫操作指令
  9. Master → Slave:傳播寫指令(Replication Stream)
 10. Slave:重播執行指令,保持數據一致

1. 全量同步階段

當一個從節點(Slave)第一次連接到主節點(Master),或者與主節點斷開時間過長無法進行部分同步時,會觸發全量同步:

  1. 從節點向主節點發送 SYNC 指令。
  2. 主節點接收到 SYNC 後,在背景執行 bgsave,生成一份目前的 RDB 二進位快照。
  3. 快照完成後,主節點將 RDB 檔案內容封裝為 RESP 傳送給從節點。
  4. 從節點接收 RDB,清空自己目前的資料庫,加載該 RDB 快照。此時,從節點的狀態與主節點執行 bgsave 那個瞬間完全一致。

2. 增量同步(傳播)階段

在全量同步期間與完成後,主節點接收到的所有寫入指令(如 SET, DEL),都會在本地執行成功的同時,將該寫指令的 RESP byte stream,發送給所有連接中的從節點。

從節點收到指令後直接在自己的資料庫中 replay 執行。這就是 Replication Stream (複製流)


為什麼主從複製只允許「單向傳播」?

在 Redis 主從複製中,資料流是單向的——只能從 Master 流向 Slave。

  • Master:可讀、可寫。
  • Slave:預設是唯讀的(Read-Only)。

這樣做是為了讓資料流向保持單純。如果 Slave 也能寫入,兩邊同時改同一個 Key 時就得處理衝突。這邊老實說一開始我也想過雙向同步,但光想解衝突就知道會寫出一堆 Bug,還是單向傳播省事又安全。


跑起來看看

來測一下我們的 AUTH 有沒有發揮作用。

# 在 redis-cli 連線到設定了密碼的伺服器
$ redis-cli
> GET mykey
# 預期回覆:(error) NOAUTH Authentication required.

> AUTH mypassword
# 預期回覆:OK

> GET mykey
# 預期回覆:(nil) 或是資料

沒密碼連看都不給看,這下安全多了!


總結

今天先把主從複製的全量同步和增量同步流程摸熟,也釐清 SYNC 在整個流程裡的位置。

明天就來動手寫從節點的背景同步和 RDB 載入,讓它自己連上主節點把資料拖回來,感覺會有點挑戰。


上一篇
Day 25:記憶體淘汰機制(Eviction Policy)LFU 演算法原理解析與實作
下一篇
Day 27:實作主從複製 - 從節點背景同步 goroutine與 RDB 全量加載
系列文
手刻 Redis:用 Go 從零打造高效能高併發的記憶體資料庫30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言