目錄
- 一、復制介紹
- 二、復制配置
- 2.1 建立復制
- 2.1.1 命令
- 2.1.2 演示
- 2.2 斷開復制
- 3.2.1 直接斷開
- 3.2.2 切換到其他master
- 2.1 建立復制
- 三、拓撲結構
- 四、復制程序
- 五、資料同步原理
- 5.1 psync命令需要的組件
- 5.1.1 主從復制偏移量
- 5.1.2 主節點復制積壓緩沖區
- 5.1.3 主節點運行id
- 5.2 psync命令
- 5.3 全量復制
- 5.4 部分復制
- 5.1 psync命令需要的組件
- 六、主從心跳
- 6.1 流程
- 6.2 repl -timeout引數
- 七、全量復制場景
- 七、一些配置和命令
一、復制介紹
主從復制,是把一臺redis服務器上資料復制到其他服務器的機制,其中前者被稱為主節點(master),后者被稱為從節點(slave),
主從復制的主要主要作用:
- 資料冗余:資料熱備,多機備份,
- 故障恢復:當主節點出現問題時,可以讓從節點提供服務,是一種功能的冗余,
- 負載均衡:可以讓主節點寫,從節點多,可以把壓力分配到多個從節點,從而實作負載均衡,
- 高可用基石:主從復制是實作哨兵和集群的基礎,
默認情況下,每個redis服務器都是master節點,每一個master可以有多個slave節點,但是一個salve節點只能有一個master節點,
二、復制配置
2.1 建立復制
2.1.1 命令
- 在組態檔中加入:slaveof {masterHost} {masterPort}
- 在redis-server啟動命令后加入 -- slaveof {masterHost} {masterPort}
- 直接使用命令(在客戶端執行): slaveof {masterHost} {masterPort}
2.1.2 演示
準備節點
默認6380埠作為master節點,再啟動一個6380節點作為salve節點,
復制一個組態檔,命名為redis6380.conf
配置新的埠號

兩個redis實體已經啟動,

執行復制命令
啟動兩個實體


執行slaveof命令

查看效果
master節點寫入,讀取

slave節點讀取資料

至此,復制搭建成功,資料已經成功從master復制到了slave,并且通過salve讀取成功,
2.2 斷開復制
3.2.1 直接斷開
直接使用slaveof no one命令即可斷開和master的復制關系

斷開復制關系后的資料
- 原有已經復制的資料會保留
- master后續寫入的資料將不再同步
可以看到原有的資料保留了
斷開后在原有master寫入

資料將不再同步到6380

3.2.2 切換到其他master
可以通過切換到其他master的方式斷開和當前master的系結,但是和slave no one不同的是,切換新的master后,從原有master復制過來的資料會被清空,

三、拓撲結構
一對一,一對多,樹狀結構,
四、復制程序
4.1保存主節點
執行slaveof后從節點只是保存了主節點的地址資訊變直接回傳,復制流程還沒有正式開始,
4.2 主從建立socket連接
從節點內部通過每秒運行的定時任務來處理相關邏輯,當定時任務發現存在新的主節點后,會嘗試和主節點建立網路連接,
從節點會創建一個socket去連接主節點,后續資料同步都是基于這個socket進行,
如果從節點無法建立連接,定時任務會無限重試到連接成功或者復制被取消為止,
4.3 發送ping命令
連接建立成功后從節點會向主節點發送ping請求進行首次通信,主要有如下目的:
- 檢測之前建立的socket是否可用,
- 檢測主節點當前是否可接受處理命令
發送ping命令后如果從節點沒有收到pong回復或者超時(比如網路超時,或者主節點阻塞無法處理等),從節點會斷開復制,下次定時任務發起后重新連接,
4.4 權限驗證
如果主節點設定了requirepass引數,則需要密碼驗證,從節點必須配置masterauth引數保證與主節點相同的密碼才能通過驗證,如果驗證失敗,從節點會斷開復制,下次定時任務發起后重新連接,
4.5 資料同步
主從復制連接建立成功后,便開始資料同步,屬于資料的初始化,主節點會把持有的所有資料發送給從節點,主題是實作方式是從節點給主節點發送psync命令(2.8之前是sync命令),這塊是耗時最長的步驟,分為全量同步和部分同步,
4.6 命令持續同步
當主節點把當前的資料同步給從節點后,便完成了復制的建立流程,后續主節點會持續的把命令發送給從節點,保證主從一致,
五、資料同步原理
主從建立連接成功后,從節點會向主節點發送psync命令來完成資料同步,同步程序分為:全量復制和部分復制,
- 全量復制:一般用于初次復制場景,主節點一次性把全部資料發給從節點,是一個比較重的操作
- 部分復制:用于處理在主從復制中因網路閃斷等原因造成的資料丟失的場景,當主從再次連接后,如果主節點完整保存了中斷期間的資料,主節點會補發丟失的資料給從節點,補發的資料遠遠小于全量資料,部分復制有效避免了全量復制的過高開銷,
5.1 psync命令需要的組件
psync命令運行需要以下組件的支持:
- 主從復制偏移量
- 主節點復制擠壓緩沖區
- 主節點運行id
5.1.1 主從復制偏移量
master節點處理完寫入命令后,會把命令的位元組長度做累加記錄,

從節點再接收到主節點發送的命令后,也會累加自身的偏移量,

通過對比master的偏移量和slave的偏移量來看slave和master的資料差異大小,
5.1.2 主節點復制積壓緩沖區
復制緩沖區是保存在主節點上的一個固定長度佇列,默認大小為1MB,當有slave時候回創建緩沖區,這時主節點回應寫命令時,不但會把命令發送給從節點,還會寫入復制擠壓緩沖區,

擠壓緩沖區是一個先進先出的佇列,如果超過容量,之前的資料會被覆寫,大小是可以配置的,擠壓緩沖區主要為了部分復制做準備,可以通過info replication來查看:
repl_backlog_active:1 //開啟復制緩沖區
repl_backlog_size:1048576 //緩沖區最大長度
repl_backlog_first_byte_offset:4505 //起始變異量,計算當前緩沖區可用范圍
repl_backlog_histlen:5460 //已保存資料的有效長度
5.1.3 主節點運行id
每個redis節點(主從)啟動后都會生成一個40位的16進制的字串作為運行id,用于唯一識別一個redis節點,從節點會保存主節點的運行id用于識別自己正在復制的是哪一個主節點,redis重啟后id會改變,

初次復制時,從節點會保存主節點的runid,
5.2 psync命令
從節點通過給主節點發送psync命令實作部分復制或者全量復制,命令格式為:
psync {runid} {offset}
- runid:所輔助主節點的runid,
- offset:當前從節點的資料偏移量
第一次復制時沒有offset和主節點的runid,會發送psync -1命令

5.3 全量復制

- 首次復制發送 psync ? -1
- master 繼續請求發現是全量復制,恢復fullresync {runid} {offset}
- slave保存主節點回應的runid和 offset
- 主節點執行bgsave,并且把從選擇開始的命令同時寫入一個緩沖區(復制緩沖區)
- 主節點執行完bgsave后把最終生成的rdb發給salve,
- salve收到主節點發送過來的rdb后開始清空自身資料
- salve把主節點的rdb載入自己的rdb,此時salve的資料更新至主節點執行bgsave時候的狀態,
- 主節點將復制緩沖區的命令發送給salve
- slave執行接收到的復制緩沖區的命令,至此salve的資料更新至主節點的最新狀態
- 如果slave開啟了aof,則會立即做bgrewriteaof,確保全量復制后aof持久化檔案立即可用,
5.4 部分復制
部分復制時redis針對全量復制開銷過高做出的一種優化措施,使用psync {runid}{offset}命令實作,
當主從復制的程序中,如果出現網路閃斷或者命令丟失等例外情況,從節點會要求主節點補發資料,如果此時主節點的復制積壓緩沖區記憶體中剛好存在這部分資料(就是斷網這段時間沒有同步到從節點的資料),則直接發給從節點,最終保持了和從節點的一直,也避免了大規模的全量復制,

- 如果主從節點之間網路出現中斷,如果超過repl-timeout時間,主節點會認為從節點故障并中斷復制連接,
- 主從斷開后,主節點依然在回應命令,這個時候新的命令無法同步到從節點,主從出現了不一致,上面也解釋了主節點會默認將命令寫入到復制積壓緩沖區,默認為1M,超出后會覆寫,
- 網路恢復了,從節點再次連接主節點,連接建立成功,
- 從節點保存了主節點的runid和自身的復制偏移量(offset),通過psync {runid} {offset}命令和主節點進行互動
- 主節點如果發現滿足部分復制的條件(后面詳細解釋這個條件),則回傳continue給從節點
- 主節點根據偏移量把復制積壓緩沖區的資料發給從節點,最終保證主從復制進入正常,
主節點判斷判斷滿足部分復制的條件
- runid必須和自身一致
- 從節點發過來的偏移量之后的資料都在自身的復制積壓緩沖區內,這個很好理解,比如從節點發過來的offset是10(代表10以后的資料都沒有同步),但是緩沖區的offset是15(說明15之前的的資料已經不在緩沖區了),這個時候就沒辦法進行部分復制
如果不滿足部分復制條件,則主節點會回傳fullsync給從節點,從節點會開啟全量復制,
由此可見復制積壓緩沖區的大小比較重要,如果太小,會被覆寫,最終導致主從網路恢復后無法進行部分復制,這個值得大小應該要基于網路的中斷時間,已經主節點的qps和命令的大小來進行計算,然后進行合理的設定,
六、主從心跳
6.1 流程
主從心跳檢測示意圖

-
master會周期性的ping slave,周期時間通過repl-ping-replica-period引數來控制,默認是10秒
-
slave每隔1秒回向master發送replconf ack {offset}命令:
-
實時監測主從節點的網路狀態
-
上報自身的資料復制偏移量,如果主節點發現從節點有資料缺失,主節點會從自身的復制積壓緩沖區中拉取資料發給從節點,
-
實作從節點的數量和延遲性功能,通過min-replicas-to-write(最小可用的從節點個數)和min-replicas-max-lag(允許的最小延遲秒,一般為0,或者1)引數定義,
-
如果master開啟了這兩個引數,那么如果可用的從節點小于min-replicas-to-write或者延遲大于min-replicas-max-lag,master會拒絕資料寫入,示意圖如下,

-
-
6.2 repl -timeout引數
redis.conf有個repl-timeout引數:
-
slave角度,如果在repl-timeout時間內沒有收到傳輸的rdb snapshot資料,
-
slave角度,如果在repl-timeout沒有收到master發送的資料包或者ping,
-
master角度,如果在repl-timeout時間沒有收到REPCONF ACK確認資訊,
當redis檢測到repl-timeout超時(默認值60s),將會關閉主從之間的連接,redis slave會重新建立主從連接的請求,這個值一定要大于repl-ping-replica-period引數
為了降低主從延遲,一般建議把redis的主從節點部署在相同的機房,
七、全量復制場景
全量復制非常重,應該盡量避免,下面是一些會導致全量復制的操作,
- 第一次建立復制,無法避免,建議低峰時候進行
- runid不匹配,從節點會保存主節點的runid,如果主節點重啟,則主節點的runid會改變,發現和從節點保存的runid不一致時,會進行全量復制,應該避免重啟,比如可以采用debug reload命令,或者采用故障轉移功能,當主節點發生故障后,可以將從節點提升為主節點,或者采用哨兵或者集群方案
- 復制積壓緩沖區不足(repl-backlog-size),這個緩沖區默認大小為1M,當超過1m后覆寫,主從中斷再次連接后如果從節點的offset在復制積壓緩沖區找不到,則會導致全量復制,這個緩沖區的大小要基于網路狀況,命令大小,以及qps進行計算配置,
七、一些配置和命令
- salve-read-only=yes, 從節點只讀,如果從節點修改,會造成主從資料不一致
- repl-disable-tcp-nodelay 是否關閉tcp_nodelay,默認為no,建議配置為yes,這個是服務器tcp的一個功能,tcp nagle演算法
- debug reload,不會導致runid改變,但是會情況記憶體資料,再次從rdb加載,
- ,,,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/241293.html
標籤:NoSQL
上一篇:高性能MySQL學習總結一
