Redis 的主從同步(複製) Redis 的主從同步(複製) 什麼是主從同步(複製) 假設有兩個 redis 實例 ⇒ A 和 B B 實例的內容與 A 實例的內容保持同步 那麼稱 A 實例是主資料庫,B 實例是從資料庫 這個過程稱為主從同步 為什麼要使用主從同步(複製) 防止發生單點故障 擴展內 ...
Redis 的主從同步(複製)
Redis 的主從同步(複製)
什麼是主從同步(複製)
假設有兩個 redis 實例 ⇒ A 和 B
B 實例的內容與 A 實例的內容保持同步
那麼稱 A 實例是主資料庫,B 實例是從資料庫
這個過程稱為主從同步
為什麼要使用主從同步(複製)
- 防止發生單點故障
- 擴展記憶體
如何開啟/關閉主從同步
開啟同步
- 配置文件中加入
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個變數:
- 伺服器的運行 ID (run ID)
- 當實例重啟時,會生成40個隨機的十六進位字元
- 主伺服器的複製積壓緩衝區(replication backlog)
- 主伺服器每將一個命令傳送給從資料庫,都會將命令放到一個積壓隊列(固定長度的迴圈隊列)中
- 主伺服器的複製偏移量(replication offset)
- 主伺服器將命令放到積壓隊列中時,會記錄下當前命令的偏移量,併發送給從伺服器
- 從伺服器的複製偏移量
- 從伺服器接收到主伺服器發送過來的命令與偏移量
也許將這4個變數列出來之後,有讀者就可以直接想象出來是怎麼實現的了,對,沒錯,就是這麼實現的
過程:
部分重同步流程
步驟 | 主伺服器 | 從伺服器 |
---|---|---|
1 | 發送命令 PSYNC 主資料庫的運行ID 斷開前最新的命令偏移量 | |
判斷 1. 運行ID是否能夠對應 2. 斷開前最新的命令偏移量是否在隊列中 滿足上述條件可以執行部分重同步,否則執行完全同步 | ||
2 | 發送給從資料庫偏移量之後的命令 | |
3 | 執行命令 |
總結
redis 在很多細節上優化了性能,主從同步(複製)的優化只是其中的一方面。