一文了解:Redis主從復制


Redis主從復制

主從復制

主從復制,將一台Redis服務器的數據,復制到其他Redis服務器。前者稱為主(master)節點,后者稱為從(slave)節點 。
在默認的情況下,Redis都是主節點,每個從節點只能有一個主節點,一個主節點可以有多個從節點。復制的數據只能從主節點復制到從節點。

配置方式

  1. 在從節點的配置文件中配置:slaveof {masterip} {masterport}
  2. 在redis-server啟動命令后加入:--slaveof {masterip} {masterport}
  3. 在redis客戶端使用命令:slaveof {masterip} {masterport}

建立主從關系

啟動兩個實例

//實例一:默認端口6379
./redis-server

//實例二:修改端口為6380
./redis-server --port 6380

結果如下圖

master

salve

建立主從連接

// 把端口為6380的redis-server掛在6379的redis-server下
./redis-cli -p 6380
127.0.0.1:6380> slaveof 127.0.0.1 6379
OK
主節點添加key
127.0.0.1:6379} set masterKey 'This is master Key'
OK
從節點查詢key
127.0.0.1:6380> get masterKey
"This is master Key"

可以發現主節點的Key已經同步到從節點了

主節點刪除key
127.0.0.1:6379} del masterKey
(integer) 1
從節點再次查詢key
127.0.0.1:6380> get masterKey
(nil)

可以發現從節點的key也已經被刪除了

斷開連接

通過slaveof {masterip} {masterport}命令建立主從復制關系以后,可以通過slaveof no one斷開。從節點斷開復制后,不會刪除已有的數據,只是不再接受主節點新的數據變化。

使用命令slaveof no one
127.0.0.1:6380> slaveof no one
OK

原理

在從節點執行slaveof命令后,主從復制的過程就開始了,可以分為6個步驟:

保存主節點信息

//從節點的redis-server中日志
27604:S 21 Aug 22:38:56.934 * SLAVE OF 127.0.0.1:6379 enabled (user request from 'id=3 addr=127.0.0.1:60092 fd=8 name= age=69 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=slaveof')

從上面的日志中可以看到salveof中的masterhost和masterport都被保存了下來。

建立連接

//從節點的redis-server中日志
27604:S 21 Aug 22:38:57.444 * Connecting to MASTER 127.0.0.1:6379
27604:S 21 Aug 22:38:57.445 * MASTER {-} SLAVE sync started

從節點內部會使用一個每秒運行的定時任務,當發現了新的主節點后根據主節點的host和port建立一個socket連接。

當連接失敗的時候定時任務會無限重試連接直到連接成功或者使用slaveof on one命令取消主從連接。

//從節點的redis-server中日志
27639:S 21 Aug 22:50:02.825 # Error condition on socket for SYNC: Connection refused

發送ping命令

連接建立成功后從節點(salve)發送ping命令進行首次通信,主要目的是:

  • 檢查主從之間網絡套接字是否可用
  • 檢查主節點當前是否可接受處理命令

從節點發送ping命令后會收到主節點的pong回復或者是超時問題,從節點便會斷開連接,下次定時任務時再次發送ping命令

發送PING命令

權限驗證

如果主節點設置了requierpass參數,則從節點必須配置masterauth參數進行密碼驗證。

從節點會向主節點發送auth命令進行驗證,auth參數為masterauth參數的值。如果驗證沒通過從節點會斷開連接,並重連

從節點發送端口信息

身份驗證之后,從節點會向主節點發送其監聽的端口號,主節點將該信息保存到該從節點對應的客戶端的slave_listening_port字段中

數據同步

主從復制能正常通信后,首次建立連接后主節點會把全部數據發送給從節點,相當於從節點完成數據初始化工作。

同步的方式有全量同步和部分同步。

命令復制

當主節點把所有數據復制給從節點后,主節點會把命令傳輸給從節點,從節點接收到命令后執行,以保證數據完整性

數據同步方式

Redis數據同步方式有全量同步和部分同步,Redis使用psync命令進行主從同步。

psync命令需要以下組件支持:

  • 主從節點各自復制偏移量
  • 主節點復制積壓緩沖區
  • 主節點運行id

復制偏移量

主節點和從節點都會維護自身復制偏移量(offset),主節點在處理完命令后,會將命令的字節長度做累加並記錄,統計在info replication中的master_repl_offset中。

127.0.0.1:6379> info replication
# Replication
role:master
...
master_repl_offset:308

從節點在接收到主節點發送的命令后,同樣累計記錄自身的偏移量,統計在info replication中的slave_repl_offset中。

127.0.0.1:6380> info replication
# Replication
role:slave
...
slave_repl_offset:1050

從節點每秒鍾把自身的復制偏移量上報給主節點,主節點會保存這個從節點的復制偏移量。記錄在從節點對應的ip,port行的offset中

127.0.0.1:6379> info replication
# Replication
role:master
...
slave0:ip=127.0.0.1,port=6380,state=online,offset=308,lag=1

復制積壓緩沖區

復制積壓緩沖區是主服務器維護的一個固定長度,先進先出的隊列,默認為1M大小。當主節點有連接的從節點時被創建,主節點將命令發送給從節點時,還會寫入復制積壓緩沖區,作為寫命令的備份,並且會為隊列里的每個字節記錄相應的復制偏移量。

復制積壓緩沖區的一些數據保存在info replication中

127.0.0.1:6379> info replication
# Replication
role:master
...
repl_backlog_active:1                   # 開啟復制積壓緩沖區
repl_backlog_size:1048576               # 緩沖區最大長度
repl_backlog_first_byte_offset:1        # 起始偏移量,計算當前緩沖區可用范圍
repl_backlog_histlen:308                # 已保存數據的有效長度

主節點運行ID

每個Redis節點在啟動后都會動態分配一個唯一的40位十六進制字符串作為運行ID(run_id)。當Redis重啟后,運行ID也會改變。

127.0.0.1:6379> info server
# Server
...
run_id:9cc202d7825028c28e91207452e993de8cdb145c
tcp_port:6379
...

當主從節點第一次復制的時候,主節點會將run_id發送給從節點,從節點斷線重新連接的時候,從節點將run_id發送給主節點,主節點和當前的自身的run_id判斷是否需要全量復制。

  1. 當從節點發送run_id和主節點當前的run_id不相同,說明從節點在斷線前和斷線后的主節點不相同,需要全量復制
  2. 當從節點發送run_id和主節點當前的run_id相同,主節點根據復制偏移量和復制積壓緩沖區判斷是需要全量復制還是部分復制

psync命令

從節點使用psync {run_id} {offset}命令完成全量復制或者部分復制

  1. run_id:從節點保存的主節點run_id
  2. offset:從節點的復制偏移量

psync運行流程
(psync運行流程, 圖片來自《Redis設計與實現》)

從節點向主節點發送命令

  • 從節點從未執行過slaveof或者最近一次執行了slaveof no one,從節點向主節點發送psync ? -1請求全量復制。
  • 從節點執行過slaveof,從節點向主節點發送psync {run_id} {offset}命令,主節點判斷是否需要全量復制。

主節點判斷是否需要全量復制

  • 主節點根據pysnc參數和自身服務器狀態,判斷是全量復制還是部分復制
  • 如果主節點的Redis版本小於2.8,則返回+ERR,從節點發送重新sync命令觸發全量復制
  • 如果主節點的run_id和psync命令中run_id參數相同,且命令中的offset參數之后的數據都存在復制積壓緩沖區,則返回+CONTINUE,從節點等待主節點的部分復制
  • 如果主節點的run_id和psync命令中run_id參數不同,或者命令中的offset參數之后的數據有部分不再復制積壓緩沖區中,則返回+FULLRESYNC {run_id} {offset},從節點觸發全量復制,並且保存主節點的run_id和offset

心跳機制

主從復制建立之后,主從節點之間會維護兩個心跳機制

心跳

PING

主節點向從節點默認每隔10秒發送PING命令,判斷從節點是否存活和連接狀態。配置參數repl-ping-slave-period可以控制PING命令的頻率。

REPLCONF ACK

從節點向主節點默認每隔1秒發送replconf ack {offset}命令。它的作用是:

實時監測主從節點網絡狀態
127.0.0.1:6379> info replication
# Replication
role:master
...
slave0:ip=127.0.0.1,port=6380,state=online,offset=308,lag=1

在主節點的info replication中可以看到lag=1,表示主節點上次收到replconf ack命令的間隔,正常情況下應該為0或者1

上報自身的偏移量

從節點上報自身偏移量判斷是否丟失數據,主節點把自身的offset和從節點的offset,如果從節點丟失數據,主節點會推送數據給從節點,如果從節點的offset之后的數據不在復制積壓緩沖區中,則需要全量復制否則為部分復制。

實現保證從節點的數量和延遲功能

主節點中使用min-slaves-to-write(默認3個)和min-slaves-max-lag(默認10s)參數,保證從節點小於3個或所有從節點延遲大於10秒,主節點拒絕執行寫命令。從節點的延遲數據是通過replconf ack命令的時間判斷的,保存在info replication中的lag信息中。如果超過repl-timeout(默認60s)配置的值,則判斷從節點下線並斷開復制連接。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM