文章目錄
1. 主從複製簡介
1.1 單擊Redis的風險與問題
單機即在一臺機器上部署一個redis節點,主要會存在以下問題:
- 機器故障
- 現象:硬盤故障、系統崩潰
- 本質:數據丟失,很可能對業務造成災難性打擊
- 結論:基本上會放棄使用Redis
- 容量瓶頸
- 現象:內存不足,從16G升級到64G,從64G升級到128G,無限升級內存
- 本質:窮或硬件條件跟不上
- 結論:放棄使用Redis
爲了避免單點Redis服務器故障,準備多臺服務器,互相連通。將數據複製多個副本保存在不同的服 務器上,連接在一起,並保證數據是同步的。即使有其中一臺服務器宕機,其他服務器依然可以繼續提供服務,實現Redis的高可用,同時實現數據冗餘備份。
1.2 多臺服務器連接方案
- 提供數據方:master,也可以叫做主服務器、主節點、主庫
- 接收數據防:slave,從服務器、從節點、從庫
- 需要解決的問題:數據同步
- 核心工作:master的數據複製到slave中
1.3什麼是主從複製
主從複製,是指將一臺Redis服務器的數據,即時、有效的複製到其他的Redis服務器。前者稱爲主節點(master),後者稱爲從節點(slave);數據的複製是單向的,只能由主節點到從節點。
- 特徵
一個master可以擁有多個slave,一個slave只對應一個master
- 職責
- master:
寫數據
執行寫操作時,將出現變化的數據自動同步到slave
讀數據(可忽略)- slave:
讀數據
寫數據(禁止)
1.3 主從複製的作用
- 讀寫分離:master寫、slave讀,提高服務器的讀寫負載能力
- 負載均衡:基於主從結構,配合讀寫分離,由slave分擔master負載,並根據需求的變化,改變slave的數 量,通過多個從節點分擔數據讀取負載,大大提高Redis服務器併發量與數據吞吐量
- 故障恢復:當master出現問題時,由slave提供服務,實現快速的故障恢復
- 數據冗餘:實現數據熱備份,是持久化之外的一種數據備份方式
- 高可用基石:基於主從複製,構建哨兵模式與集羣,實現Redis的高可用方案
2. 主從複製的使用
2.1 建立主從結構
需要注意,主從複製的開啓,完全是在從節點發起的,不需要我們在主節點做任何事情。
從節點開啓主從複製,有3種方式:
- 客戶端發送命令
slaveof <masterip> <masterport>
注意是從服務器的客戶端發送命令
- 啓動服務器參數
redis-server --slaveof <masterip> <masterport>
注意是在從服務器的啓動命令(redis-server)後加--slaveof <masterip> <masterport>
- 服務器配置
slaveof <masterip> <masterport>
注意是在從服務器的配置文件中加入此配置
工作中一般使用的是第三種方式,開啓了主從複製之後,可以在服務器(包括主從)開啓的頁面中看到相關信息,並且主服務器會自動將數據同步到從服務器中,不需要你做任何操作。
2.2 斷開主從
通過slaveof 命令建立主從複製關係以後,可以通過從服務器客戶端執行
slaveof no one
命令斷開。需要注意的是,從節點斷開復制後,不會刪除已有的數據,只是不再接受主節點新的數據變化。
3. 主從複製的工作流程
主從複製過程大致可以分爲3個階段
- 建立連接階段
- 數據同步階段
- 命令傳播階段
3.1 建立連接階段
建立slave到master的連接,使master能夠識別slave,並保存slave端口號
- 工作流程
slave 工作流程
- 步驟1:設置master的地址和端口,保存master信息
- 步驟2:建立socket連接
- 步驟3:發送ping命令(定時器任務)
- 步驟4:身份驗證
- 步驟5:發送slave端口信息
如圖,左邊是master做的事情,右邊是slave做的事情
最終達到的狀態
- slave:保存master的地址與端口號
- master:保存slave的端口號
- 總體:之間創建了socket連接
3.2 數據同步階段
-
在slave初次連接後,複製master中的所有數據到slave,全量複製
-
將slave的數據庫狀態更新成master當前的數據庫狀態(全量複製過程中,新的數據變化),部分複製
-
工作流程
slave 工作流程
- 步驟1:請求同步數據
- 步驟2:創建RDB同步數據
- 步驟3:恢復RDB同步數據
- 步驟4:請求部分同步數據
- 步驟5:恢復部分同步數據
至此,數據同步工作完成
最終達到的狀態
- salve:具有master端全部數據,包含RDB過程接收的數據
- master:保存slave當前數據同步的位置
- 總體:之間完成了數據克隆
注意
- 在數據同步階段之前,從節點是主節點的客戶端,主節點不是從節點的客戶端;而到了這一階段及以後,主從節點互爲客戶端。原因在於:在此之前,主節點只需要響應從節點的請求即可,不需要主動發請求,而在數據同步階段和後面的命令傳播階段,主節點需要主動向從節點發送請求(如推送緩衝區中的寫命令),才能完成複製。
- 如果網絡中斷時間過長,導致主節點沒有能夠完整地保存中斷期間執行的寫命令(緩衝區中的指令被擠出去了),則無法進行部分複製,仍使用全量複製。
- 複製緩衝區大小設定不合理,會導致數據溢出。如進行全量複製週期太長,進行部分複製時發現數據已 經存在丟失的情況,必須進行第二次全量複製,致使slave陷入死循環狀態。 可以使用 repl-backlog-size 屬性配置緩衝區大小
- 主節點通過網絡將RDB文件發送給從節點,對主從節點的帶寬都會帶來很大的消耗
- 主節點通過bgsave命令fork子進程進行RDB持久化,該過程是非常消耗CPU、內存(頁表複製)、硬盤IO的
- 從節點首先清除自己的舊數據,然後執行RDB文件恢復數據
3.3 命令傳播階段
數據同步階段完成後,主從節點進入命令傳播階段;在這個階段,主節點將自己執行的寫命令發送給從節點,從節點接收命令並執行,從而實時的保證主從節點數據的一致性(通過心跳機制實現)。
需要注意的是,命令傳播是異步的過程,即主節點發送寫命令後並不會等待從節點的回覆;因此實際上主從節點之間很難保持實時的一致性,延遲在所難免。數據不一致的程度,與主從節點之間的網絡狀況、主節點寫命令的執行頻率、以及主節點中的repl-disable-tcp-nodelay配置等有關。
- 命令傳播階段出現斷網現象
- 網絡閃斷閃連 ——忽略
- 短時間網絡中斷 ——部分複製
- 長時間網絡中斷 ——全量複製
3.4 部分複製的核心要素
部分複製除了用於同步階段外,還用於網絡中斷等情況後的複製,只將中斷期間主節點執行的寫命令發送給從節點,與全量複製相比更加高效。需要注意的是,如果網絡中斷時間過長,導致主節點沒有能夠完整地保存中斷期間執行的寫命令,則無法進行部分複製,仍使用全量複製。部分複製的實現,依賴於下面三個重要的概念:
- 服務器運行ID(runid)
- 概念:服務器運行ID是每一臺服務器每次運行的身份識別碼,一臺服務器多次運行可以生成多個運行id
- 組成:運行id由40位字符組成,是一個隨機的十六進制字符 例如fdc9ff13b9bbaab28db42b3d50f852bb5e3fcdce
- 作用:運行id被用於在服務器間進行傳輸,識別身份 ,如果想兩次操作均對同一臺服務器進行,必須每次操作攜帶對應的運行id,用於對方識別
- 實現方式:運行id在每臺服務器啓動時自動生成的,master在首次連接slave時,會將自己的運行ID發 送給slave,slave保存此ID,通過info Server命令,可以查看節點的runid
- 複製緩衝區
在命令傳播階段,主節點除了將寫命令發送給從節點,還會發送一份給複製積壓緩衝區,作爲寫命令的備份
- 概念:複製緩衝區,又名複製積壓緩衝區,是一個先進先出(FIFO)的隊列,用於存儲服務器執行過的命令,每次傳播命令,master都會將傳播的命令記錄下來,並存儲在複製緩衝區 。 複製緩衝區默認數據存儲空間大小是1M,由於存儲空間大小是固定的,當入隊元素的數量大於隊 列長度時,最先入隊的元素會被彈出,而新元素會被放入隊列
- 由來:每臺服務器啓動時,如果開啓有AOF或被連接成爲master節點,即創建複製緩衝區
- 作用:用於保存master收到的所有指令(僅影響數據變更的指令,例如set,select)
- 數據來源:當master接收到主客戶端的指令時,除了將指令執行,會將該指令存儲到緩衝區中
- 複製緩衝區工作原理
組成
- 偏移量
- 字節值
工作原理
- 通過offset區分不同的slave當前數據傳播的差異
- master記錄已發送的信息對應的offset
- slave記錄已接收的信息對應的offset
- 主節點根據offset和緩衝區大小決定能否執行部分複製,如果offset偏移量之後的數據,仍然都在複製積壓緩衝區裏,則執行部分複製;如果offset偏移量之後的數據已不在複製積壓緩衝區中(數據已被擠出),則執行全量複製。也就是判斷指令是否被擠出去,如果被擠出,就全量複製,沒有被擠出去,就部分複製
- 偏移量
- 概念:一個數字,描述複製緩衝區中的指令字節位置
- 分類:
master複製偏移量:記錄發送給所有slave的指令字節對應的位置(多個)
slave複製偏移量:記錄slave接收master發送過來的指令字節對應的位置(一個)- 數據來源
master端:發送一次記錄一次
slave端:接收一次記錄一次- 作用
同步信息,比對master與slave的差異,當slave斷線後,恢復數據使用
3.4 數據同步和命令傳播階段詳細工作流程
3.5 心跳機制
- 在命令傳播階段,master與slave間需要進行信息交換,使用心跳機制進行維護,實現雙方連接保持在線
master 心跳
指令:ping
週期:由repl-ping-slave-period 決定,默認10秒
作用:判斷slave 是否在線
查詢:info replication 獲取slave最後一次連接時間間隔,lag 項維持在0或1視爲正常slave 心跳
- 指令:
replconf ack offset
- 週期:1秒
- 作用:彙報slave自己的複製偏移量,獲取最新的數據變更指令。判斷master是否在線
- 心跳階段注意事項
- 當slave多數掉線,或延遲過高時,master爲保障數據穩定性,將拒絕所有信息同步操作,使用下面兩個參數進行配置
min-slaves-to-write 2
主從複製的最小slave數
min-slaves-max-lag 8
主從複製所有slave的最大延遲
slave數量少於2個,或者所有slave的延遲都大於等於8秒時,強制關閉master寫功能,停止數據同步
slave數量和延遲由slave發送REPLCONF ACK命令做確認
3.6 完整流程
4. 主從複製常見問題
- 頻繁的全量複製
伴隨着系統的運行,master的數據量會越來越大,一旦master重啓,runid將發生變化,會導致全部slave的 全量複製操作
- 內部優化調整方案
- master內部創建master_replid變量,使用runid相同的策略生成,長度41位,併發送給所有slave
- 在master關閉時執行命令 shutdown save,進行RDB持久化,將runid與offset保存到RDB文件中 ,通過
redis-check-rdb
命令可以查看該信息- master重啓後,將RDB文件中保存的repl-id與repl-offset加載到內存中 ,通過info命令可以查看該信息
- 作用
本機上次runid,重啓後恢復該值,使所有slave認爲還是之前的master
- 頻繁的全量複製2
- 問題現象:網絡環境不佳,出現網絡中斷,slave不提供服務
- 問題原因:複製緩衝區過小,斷網後slave的offset越界,觸發全量複製
- 最終結果:slave反覆進行全量複製
- 解決方案
修改複製緩衝區大小,repl-backlog-size
- 建議設置如下:
- 測算從master到slave的重連平均時長second
- 獲取master平均每秒產生寫命令數據總量write_size_per_second
- 最優複製緩衝區空間 = 2 * second * write_size_per_second
- 頻繁的網絡中斷
- 問題現象: master的CPU佔用過高 或 slave頻繁斷開連接
- 問題原因
slave每1秒發送REPLCONF ACK命令到master
當slave接到了慢查詢時(keys * ,hgetall等),會大量佔用CPU性能
master每1秒調用複製定時函數replicationCron(),比對slave發現長時間沒有進行響應- 最終結果
master各種資源(輸出緩衝區、帶寬、連接等)被嚴重佔用- 解決方案
通過設置合理的超時時間(repl-timeout
,該參數定義了超時時間的閾值(默認60秒),超過該值,釋放slave ),確認是否釋放slave
- 頻繁的網絡中斷2
- 問題現象:slave與master連接斷開
- 問題原因
master發送ping指令頻度較低
master設定超時時間較短
ping指令在網絡中存在丟包- 解決方案
提高ping指令發送的頻度repl-ping-slave-period
,超時時間repl-time的時間至少是ping指令頻度的5到10倍,否則slave很容易判定超時
- 數據不一致
- 問題現象:多個slave獲取相同數據不同步
- 問題原因: 網絡信息不同步,數據發送有延遲
- 解決方案
優化主從間的網絡環境,通常放置在同一個機房部署,如使用阿里雲等雲服務器時要注意此現象
監控主從節點延遲(通過offset)判斷,如果slave延遲過大,暫時屏蔽程序對該slave的數據訪問
slave-serve-stale-data yes|no
開啓後僅響應info、slaveof等少數命令(慎用,除非對數據一致性要求很高)
參考: