復制
一、分類
Redis的復制功能分為同步和命令傳播兩個操作
1.同步(全量復制):
從服務器發送SLAVEOF命令,要求從服務器復制主服務器時,從服務器首先需要執行同步操作,即將從服務器的數據庫狀態更新為主服務器的數據庫狀態(主服務器生成RDB文件並發送給從服務器)
新版PSYNC命令具有完整重同步和部分重同步兩種模式
-
完整重同步
用於初次復制情況
-
部分重同步(命令傳播)
用於處理斷線后復制情況,當從服務器在斷線后重新連接主服務器時,如果條件允許,主服務器可以將主從服務器連接斷開期間執行的寫命令發送給服務器
功能實現由三個部分構成:
-
復制偏移量:
主從服務器分別維護一個復制偏移量(判斷兩者是否處於一致狀態)
-
復制積壓緩沖區:
當主服務器進行命令傳播時,它不僅會將寫命令發送給所有從服務器,還會將寫命令入隊到復制積壓緩沖區里面。
當服務器重新連上主服務器時,從服務器會通過PSYNC命令將自己的復制偏移量offset發送給主服務器,主服務器會根據這個復制偏移量來決定對從服務器執行何種同步操作。
1) 如果offset之后的數據還在復制積壓緩沖區,執行部分重同步操作。
2) 相反,執行完整重同步操作。
-
服務器運行ID: 服務器斷線后並重新連接上一個主服務器時,從服務器將向當前連接的主服務器發送之前保存的運行ID
1) 如果相同,主服務器執行部分重同步操作
2) 如果不相同,主服務器執行完整重同步操作
-
2.命令傳播(部分復制)
主服務器會將自己執行的寫命令,也即是造成主從服務器不一致的寫命令,發送給從服務器執行
二、實現步驟
1.設置主服務器的地址和端口
SLAVEOF 127.0.0.1 6379
2.建立套接字連接
從節點內部通過每秒運行的定時任務維護復制相關邏輯,當定時任務發現存在新的主節點后,會嘗試與該節點建立網絡連接。
3.發送PING命令
連接建立成功后從節點發送ping請求進行首次通信,目的:
- 檢測主從之間的網絡套接字是否可用
- 檢測主節點在當前是否可接受處理命令
4.身份驗證(權限驗證)
如果主節點設置了requirepass參數,則需要密碼驗證,從節點必須配置masterauth參數保證與主節點相同的密碼才能通過驗證;如果驗證失敗復制將終止,從節點重新發起復制流程。
5.發送端口信息
在身份驗證步驟之后,從服務器將執行命令REPLCONF listening-port , 想主服務器發送從服務器的監聽端口號。主服務器收到這個命令后,會將端口號記錄在從服務器所對應的客戶端狀態slave_listening_port屬性中
6.同步
從服務器向主服務器發送PSYNC命令,執行同步操作,並將自己的數據庫更新至主服務器數據庫當前所處的狀態
7.命令傳播
主服務器一直將自己執行的寫命令發送給從服務器
三、心跳檢測
在命令傳播階段,從服務器默認會以每秒一次的頻率,向主服務器發送命令:
REPLCONF ACK <replication_offset>
其中,replication_offset是從服務器當前的復制偏移量
作用:
- 檢測主從服務器的網絡連接狀態
- 輔助實現min-slaves選項:防止主服務器在不安全的情況下執行寫命令
- 檢測命令丟失
四、常見問題解決思路
1.讀寫分離
- 復制數據延遲:編寫外部監控程序監聽主從節點的復制偏移量,延遲較大時觸發報警或者通知客戶端避免讀取延遲過高的從節點
- 讀到過期數據: Redis內部維護過期數據刪除策略
- 惰性刪除:每次讀取時檢查鍵是否超時,超時執行del命令刪除鍵對象
- 定時刪除:定時任務會循環采樣一定數量的鍵,發現超時刪除 Redis在3.2版本解決了這個問題,從節點讀取數據之前會檢查過期時間來決定是否返回數據
- 從節點故障問題:客戶端維護可用從節點列表,當從節點故障時立刻切換到其他從節點或主節點上
2.主從配置不一樣
3.規避全量配置
- 第一次建立復制:無法避免。建議在低峰時進行操作或者盡量避免使用大數據量的Redis節點
- 節點運行ID不匹配:架構上避免。提供故障轉移功能,手動提升從節點為主節點或者采用支持自動故障轉移的哨兵或集群方案
- 復制積壓緩沖區不足:根據網絡中斷時長,寫命令數據量分析出合理的積壓緩沖區大小
4.規避復制風暴
大量從節點對同一主節點或者對同一台機器的多個主節點短時間內發起全量復制的過程
- 單主節點復制風暴:減少主節點掛載從節點的數量,或者采用樹狀復制結構,加入中間層從節點用來保護主節點
- 單機器復制風暴:單台機器部署多個Redis實例。 避免方法:
- 應該把主節點盡量分散在多台機器上
- 當主節點所在機器故障后提供故障轉移機制,避免機器回復后進行密集的全量復制