Redis 的主從同步(復制)


Redis 的主從同步(復制)

Redis 的主從同步(復制)

什么是主從同步(復制)

假設有兩個 redis 實例 ⇒ A 和 B

B 實例的內容與 A 實例的內容保持同步

那么稱 A 實例是主數據庫,B 實例是從數據庫

這個過程稱為主從同步

為什么要使用主從同步(復制)

  1. 防止發生單點故障
  1. 擴展內存

如何開啟/關閉主從同步

開啟同步

  • 配置文件中加入
slaveof 主數據庫地址 主數據庫端口
  • 在命令行中執行上述命令
redis> slaveof 主數據庫地址 主數據庫端口
  • 在開啟從服務器時執行命令
$ reids-server --port 6380 --slaveof 主數據庫地址 主數據庫端口

關閉同步,並成為主數據庫

redis> slaveof no one

原理(實現)

復制分為連接建立,數據同步(sync)和命令傳播(command propagate)三個階段

連接建立這里不說,與復制原理無關

下面主要講數據同步與命令傳播兩個階段

redis 從 2.8 版本之后優化了復制功能,咱們先從舊版本的復制說起:

舊版復制過程

步驟 主服務器 從服務器
同步流程    
1   向主服務器發送 SYNC 命令
2 收到 SYNC 命令,執行 BGSAVE 生成 RDB 文件  
3 使用緩沖區記錄從現在的寫命令  
4 將生成的 RDB 文件發送給從服務器  
5 將緩沖區內的寫命令發給從服務器 接收並載入 RDB 文件
6   接收並執行主服務器發送來的寫命令
命令傳播流程    
1 發送客戶端發過來的寫命令  
2   執行主服務器發送過來的寫命令
斷線重連 與同步流程一致 與同步流程一致

經過上述步驟之后主從服務器的狀態可以始終保持一致。

細心的讀者已經發現了舊版復制的一些問題:

斷線重連需要重新走一次同步的流程,而同步流程中的主服務器生成 RDB 文件和從服務器執行 RDB 文件都是特別密集的 IO 操作,這會讓斷線重連的成本很高

於是從 2.8 版本之后,redis 使用了新的技術來防止重新執行同步流程

新版復制過程

步驟 主服務器 從服務器
完整同步流程    
1   向主服務器發送 PSYNC 命令
2 收到 PSYNC 命令,執行 BGSAVE 生成 RDB 文件  
3 使用緩沖區記錄從現在的寫命令  
4   接收並執行主服務器發送來的寫命令
5 將緩沖區內的寫命令發給從服務器 接收並載入 RDB 文件
6 將生成的 RDB 文件發送給從服務器  
命令傳播流程    
1 發送客戶端發過來的寫命令  
2   執行主服務器發送過來的寫命令
斷線重連過程    
1   發送 PSYNC 命令
2 向從服務器發送斷線過程中的寫命令  
3   執行寫命令

新版復制經過上述步驟,也可以實現主從數據庫狀態的一致。

在斷線重連過程中,只需要重新執行斷線過程中未同步的命令即可,這樣就比舊版的復制節省了很多 IO 操作

那么這個斷線重連的是怎么實現的呢?

部分重同步(斷線重連)的實現

redis 的部分重同步借助了4個變量:

  1. 服務器的運行 ID (run ID)
    • 當實例重啟時,會生成40個隨機的十六進制字符
  1. 主服務器的復制積壓緩沖區(replication backlog)
    • 主服務器每將一個命令傳送給從數據庫,都會將命令放到一個積壓隊列(固定長度的循環隊列)中
  1. 主服務器的復制偏移量(replication offset)
    • 主服務器將命令放到積壓隊列中時,會記錄下當前命令的偏移量,並發送給從服務器
  1. 從服務器的復制偏移量
    • 從服務器接收到主服務器發送過來的命令與偏移量

 

也許將這4個變量列出來之后,有讀者就可以直接想象出來是怎么實現的了,對,沒錯,就是這么實現的

過程:

部分重同步流程

步驟 主服務器 從服務器
1   發送命令 PSYNC 主數據庫的運行ID 斷開前最新的命令偏移量
  判斷 1. 運行ID是否能夠對應 2. 斷開前最新的命令偏移量是否在隊列中 滿足上述條件可以執行部分重同步,否則執行完全同步  
2 發送給從數據庫偏移量之后的命令  
3   執行命令

總結

redis 在很多細節上優化了性能,主從同步(復制)的優化只是其中的一方面。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM