redis-複製

1、複製介紹

主從複製,是把一臺redis服務器上數據複製到其餘服務器的機制,其中前者被稱爲主節點(master),後者被稱爲從節點(slave)。html

主從複製的主要主要做用:node

  1. 數據冗餘:數據熱備,多機備份。
  2. 故障恢復:當主節點出現問題時,可讓從節點提供服務,是一種功能的冗餘。
  3. 負載均衡:可讓主節點寫,從節點多,能夠把壓力分配到多個從節點,從而實現負載均衡。
  4. 高可用基石:主從複製是實現哨兵和集羣的基礎。

默認狀況下,每一個redis服務器都是master節點,每個master能夠有多個slave節點,可是一個salve節點只能有一個master節點。redis

2、複製配置

2.1 創建複製

2.1.1 命令

  1. 在配置文件中加入:slaveof {masterHost} {masterPort}
  2. 在redis-server啓動命令後加入 -- slaveof {masterHost} {masterPort}
  3. 直接使用命令(在客戶端執行): slaveof {masterHost} {masterPort}

2.1.2 演示

準備節點算法

默認6380端口做爲master節點,再啓動一個6380節點做爲salve節點。服務器

複製一個配置文件,命名爲redis6380.conf網絡

配置新的端口號負載均衡

兩個redis實例已經啓動。socket

執行復制命令tcp

啓動兩個實例優化

執行slaveof命令

查看效果

master節點寫入,讀取

slave節點讀取數據

至此,複製搭建成功,數據已經成功從master複製到了slave,而且經過salve讀取成功。

2.2 斷開復制

3.2.1 直接斷開

直接使用slaveof no one命令便可斷開和master的複製關係

斷開復制關係後的數據

  1. 原有已經複製的數據會保留
  2. master後續寫入的數據將再也不同步

能夠看到原有的數據保留了

斷開後在原有master寫入

數據將再也不同步到6380

3.2.2 切換到其餘master

能夠經過切換到其餘master的方式斷開和當前master的綁定。可是和slave no one不一樣的是,切換新的master後,從原有master複製過來的數據會被清空。

3、拓撲結構

一對一,一對多,樹狀結構。

4、複製過程

4.1保存主節點

執行slaveof後從節點只是保存了主節點的地址信息變直接返回,複製流程尚未正式開始。

4.2 主從創建socket鏈接

從節點內部經過每秒運行的定時任務來處理相關邏輯,當定時任務發現存在新的主節點後,會嘗試和主節點創建網絡鏈接。

從節點會建立一個socket去鏈接主節點,後續數據同步都是基於這個socket進行。

若是從節點沒法創建鏈接,定時任務會無限重試到鏈接成功或者複製被取消爲止。

4.3 發送ping命令

鏈接創建成功後從節點會向主節點發送ping請求進行首次通訊,主要有以下目的:

  1. 檢測以前創建的socket是否可用。
  2. 檢測主節點當前是否可接受處理命令

發送ping命令後若是從節點沒有收到pong回覆或者超時(好比網絡超時,或者主節點阻塞沒法處理等),從節點會斷開復制,下次定時任務發起後從新鏈接。

4.4 權限驗證

若是主節點設置了requirepass參數,則須要密碼驗證,從節點必須配置masterauth參數保證與主節點相同的密碼才能經過驗證,若是驗證失敗,從節點會斷開復制,下次定時任務發起後從新鏈接。

4.5 數據同步

主從複製鏈接創建成功後,便開始數據同步,屬於數據的初始化,主節點會把持有的全部數據發送給從節點,主題是實現方式是從節點給主節點發送psync命令(2.8以前是sync命令)。這塊是耗時最長的步驟,分爲全量同步和部分同步。

4.6 命令持續同步

當主節點把當前的數據同步給從節點後,便完成了複製的創建流程,後續主節點會持續的把命令發送給從節點,保證主從一致。

5、數據同步原理

主從創建鏈接成功後,從節點會向主節點發送psync命令來完成數據同步,同步過程分爲:全量複製和部分複製。

  1. 全量複製:通常用於初次複製場景,主節點一次性把所有數據發給從節點,是一個比較重的操做
  2. 部分複製:用於處理在主從複製中因網絡閃斷等緣由形成的數據丟失的場景,當主從再次鏈接後,若是主節點完整保存了中斷期間的數據,主節點會補發丟失的數據給從節點,補發的數據遠遠小於全量數據,部分複製有效避免了全量複製的太高開銷。

5.1 psync命令須要的組件

psync命令運行須要如下組件的支持:

  1. 主從複製偏移量
  2. 主節點複製擠壓緩衝區
  3. 主節點運行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}
  1. runid:所輔助主節點的runid,
  2. offset:當前從節點的數據偏移量

第一次複製時沒有offset和主節點的runid,會發送psync -1命令

5.3 全量複製

  1. 首次複製發送 psync ? -1
  2. master 繼續請求發現是全量複製,恢復fullresync {runid} {offset}
  3. slave保存主節點響應的runid和 offset
  4. 主節點執行bgsave,而且把從選擇開始的命令同時寫入一個緩衝區(複製緩衝區)
  5. 主節點執行完bgsave後把最終生成的rdb發給salve。
  6. salve收到主節點發送過來的rdb後開始清空自身數據
  7. salve把主節點的rdb載入本身的rdb,此時salve的數據更新至主節點執行bgsave時候的狀態。
  8. 主節點將複製緩衝區的命令發送給salve
  9. slave執行接收到的複製緩衝區的命令,至此salve的數據更新至主節點的最新狀態
  10. 若是slave開啓了aof,則會當即作bgrewriteaof,確保全量複製後aof持久化文件當即可用。

5.4 部分複製

部分複製時redis針對全量複製開銷太高作出的一種優化措施,使用psync {runid}{offset}命令實現。

當主從複製的過程當中,若是出現網絡閃斷或者命令丟失等異常狀況,從節點會要求主節點補發數據,若是此時主節點的複製積壓緩衝區內存中恰好存在這部分數據(就是斷網這段時間沒有同步到從節點的數據),則直接發給從節點,最終保持了和從節點的一直,也避免了大規模的全量複製。

  1. 若是主從節點之間網絡出現中斷,若是超過repl-timeout時間,主節點會認爲從節點故障並中斷複製鏈接。
  2. 主從斷開後,主節點依然在響應命令,這個時候新的命令沒法同步到從節點,主從出現了不一致。上面也解釋了主節點會默認將命令寫入到複製積壓緩衝區,默認爲1M,超出後會覆蓋。
  3. 網絡恢復了,從節點再次鏈接主節點,鏈接創建成功。
  4. 從節點保存了主節點的runid和自身的複製偏移量(offset),經過psync {runid} {offset}命令和主節點進行交互
  5. 主節點若是發現知足部分複製的條件(後面詳細解釋這個條件),則返回continue給從節點
  6. 主節點根據偏移量把複製積壓緩衝區的數據發給從節點,最終保證主從複製進入正常。

主節點判斷判斷知足部分複製的條件

  1. runid必須和自身一致
  2. 從節點發過來的偏移量以後的數據都在自身的複製積壓緩衝區內,這個很好理解,好比從節點發過來的offset是10(表明10之後的數據都沒有同步),可是緩衝區的offset是15(說明15以前的的數據已經不在緩衝區了),這個時候就沒辦法進行部分複製

若是不知足部分複製條件,則主節點會返回fullsync給從節點,從節點會開啓全量複製

因而可知複製積壓緩衝區的大小比較重要,若是過小,會被覆蓋,最終致使主從網絡恢復後沒法進行部分複製,這個值得大小應該要基於網絡的中斷時間,已經主節點的qps和命令的大小來進行計算,而後進行合理的設置。

6、主從心跳

6.1 流程

主從心跳檢測示意圖

  1. master會週期性的ping slave,週期時間經過repl-ping-replica-period參數來控制,默認是10秒

  2. 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參數:

  1. slave角度,若是在repl-timeout時間內沒有收到傳輸的rdb snapshot數據,

  2. slave角度,若是在repl-timeout沒有收到master發送的數據包或者ping。

  3. master角度,若是在repl-timeout時間沒有收到REPCONF ACK確認信息。

當redis檢測到repl-timeout超時(默認值60s),將會關閉主從之間的鏈接,redis slave會從新創建主從鏈接的請求。這個值必定要大於repl-ping-replica-period參數

爲了下降主從延遲,通常建議把redis的主從節點部署在相同的機房。

7、全量複製場景

全量複製很是重,應該儘可能避免,下面是一些會致使全量複製的操做。

  1. 第一次創建複製,沒法避免,建議低峯時候進行
  2. runid不匹配,從節點會保存主節點的runid,若是主節點重啓,則主節點的runid會改變,發現和從節點保存的runid不一致時,會進行全量複製,應該避免重啓,好比能夠採用debug reload命令,或者採用故障轉移功能,當主節點發生故障後,能夠將從節點提高爲主節點,或者採用哨兵或者集羣方案
  3. 複製積壓緩衝區不足(repl-backlog-size),這個緩衝區默認大小爲1M,當超過1m後覆蓋,主從中斷再次鏈接後若是從節點的offset在複製積壓緩衝區找不到,則會致使全量複製,這個緩衝區的大小要基於網絡情況,命令大小,以及qps進行計算配置。

7、一些配置和命令

  1. salve-read-only=yes。 從節點只讀,若是從節點修改,會形成主從數據不一致
  2. repl-disable-tcp-nodelay 是否關閉tcp_nodelay,默認爲no,建議配置爲yes。這個是服務器tcp的一個功能,tcp nagle算法
  3. debug reload,不會致使runid改變,可是會狀況內存數據,再次從rdb加載。
  4. 。。。
相關文章
相關標籤/搜索