Redis單機的吞吐是有上限的,在一些高并發業務場景下,我們需要對Redis進行擴展。例如,實現讀寫分離,緩解主服務器的壓力。
Replication
Redis提供了replication模式來實現主從復制。
replication主要依賴于以下三個機制:
- 當master和slave連接正常時,matser向slave發送命令來保持slave的更新,包括數據的寫入,過期,逐出
- 當slave與master的連接斷開,slave重新連接之后,slave會嘗試進行增量同步①,只更新連接中斷期間的數據
- 當slave無法執行增量同步時,會執行全量同步②
(1) 增量同步
slave 由于某些原因與 master 斷開連接,重新連接之后,只需要同步著期間缺少的數據
(2) 全量同步
master 執行 BGSAVE
指令,完成后將快照文件傳輸給 slave
Replication特點
Redis的replication有以下特點需要了解:
- Redis使用異步復制,主從之間異步的確認數據同步的數量
- 一個主可以有多個從
- 從還可以有從。從4.0版本開始,所有的從將會從master接受到完全一樣的數據①
- 復制在主服務器上是異步的,這意味著主可以在給多臺從服務器器同步時還可以處理客戶端的請求
- 復制在從服務器上也是異步的,如果從服務器在復制期間有客戶端請求,從服務器將會從舊的數據集中返回數據。可以在配置項中進行配置
- 復制可以用于擴展讀請求(實現讀寫分離)
- 可以使用復制來避免將全部數據寫入磁盤的開銷②
(1) 從服務器的數據只會從最原始的主服務器獲得
例如,A --> B --> C,存在這樣一條主從鏈,B設置為可以進行寫入操作,那么C不會獲得B中寫入的數據,只能獲得A中的數據集
(2) 不推薦這么做,在主從重新連接時,從服務器的數據如果沒辦法進行增量同步,將會刪除本地所有的數據,再同步主服務器上的數據,所以最好還是開啟持久化
配置
slaveof <masterip> <masterport>
masterauth <master-password>
slave-serve-stale-data yes # 是否異步復制
slave-read-only yes
repl-diskless-sync no # 無盤復制
repl-diskless-sync-delay 5
repl-ping-slave-period 10
repl-timeout 60
repl-disable-tcp-nodelay no
repl-backlog-size 1mb
repl-backlog-ttl 3600
slave-priority 100
min-slaves-to-write 3
min-slaves-max-lag 10
-
slaveof <masterip> <masterport>
設置從哪臺Redis服務器同步數據 -
masterauth <master-password>
設置master的密碼 -
slave-serve-stale-data
在同步數據時是否異步處理客戶端請求① -
slave-read-only
是否開啟只讀,默認yes
開啟 -
repl-diskless-sync
是否開啟無盤復制②,默認為no
-
repl-diskless-sync-delay
無盤復制延時,默認為5
,單位秒(s) -
repl-ping-slave-period
slave 發送ping的時間間隔,默認為10
,單位秒(s) -
repl-timeout
復制超時時長,默認60
,單位秒(s) -
repl-disable-tcp-nodelay
是否在同步完成之后禁用TCP_NODELAY
,默認為no
-
repl-backlog-size
backlog 體積,默認1mb
-
repl-backlog-ttl
backlog 過期時長,默認3600
,單位秒(s) -
slave-priority
從服務器權重③ -
min-slaves-to-write
④達到指定從服務器個數才開啟寫入功能,設置為0表示禁用此項,默認情況下為0 -
min-slaves-max-lag
從服務器最大滯后時間,如果超過該時長,將關閉寫入功能 ,默認為10
(1) 異步復制的同時處理客戶端請求
Redis可能會從舊的數據集中返回數據給客戶端,如果沒有舊的數據集則返回空
(2) 無盤復制
子進程直接通過網絡將RDB文件發給slave,不用使用磁盤作為中間存儲
(3) slave-priority
在Redis的哨兵中,檢測Redis可用性,如果master不可用,哨兵將會依據此項來選取從服務器提升為主服務器
(4) 達到N個從服務才開啟寫入查詢
由于Redis的異步復制,無法保證slave接收到數據,這將存在一段丟失數據的窗口期。
slave每秒向master發送ping,確認處理的數據量,master會記錄每個slave最后一次ping的時間,通過配置min-slaves-to-write N
和 min-slaves-max-lag M
來控制master的寫入查詢, 如果至少有N個slave,滯后小于M秒,master則接受寫入;如果不滿足條件,則返回error。
這是一種盡力保證數據安全的機制。其中對于給定的寫入不確保一致性,但是至少數據丟失的時間窗口被限制為給定的秒數。通常,綁定數據丟失優于未綁定數據丟失。
工作機制
-
slave
啟動,僅僅保存master
的信息,包括master
的host和ip,但是復制流程沒開始(master的host和ip是通過redis.conf里面的slaveof配置的) -
slave
內部有個定時任務,每秒檢查是否有新的master
要連接和復制,如果發現,就跟master
建立socket網絡連接 -
slave
發送ping命令給master
- 口令認證,如果master設置了requirepass,那么
slave
必須發送masterauth
的口令過去進行認證 -
master
第一次執行全量復制,將所有數據發給slave node -
master
后續持續將寫命令,異步復制給slave
從服務器怎么處理過期key
從服務器并不會主動過期數據集中的數據,主服務器在數據過期或被逐出的時候會向從服務器發送一條del的命令,將從服務器中對應的數據刪除
什么時候執行全量同步,什么時候執行增量同步?
要理解全量,增量同步的機制,先要理解Redis復制中的三個概念:
- Replication ID(復制ID),標記數據集的給定歷史記錄。每次實例從頭開始作為主服務器重新啟動,或者從服務器提升為主服務器時,將為此實例生成新的復制ID。連接到主服務器的從服務器將在握手后繼承其復制ID。
- offset(偏移量),每個主服務器還會為生成的每個復制流字節遞增一個偏移量,以便將其發送到從服務器,從服務器也會保存這個值。
- backlog(緩沖區),從服務器斷開與主服務器的連接之后,主服務器會暫時將數據存入backlog,默認1mb,有過期時間。
master
給slave
復制數據時,也會將數據在backlog中同步寫一份,backlog主要是用來做全量復制中斷候的增量復制的
從服務器由于某些原因斷開與主服務器的連接,再次連接后,從服務器上報當前的Replication ID
和 offset
,如果Replication ID
不一致則進行全量同步,如果一致則判斷 offset
,這區間的數據如果還存在 backlog
中,就進行 增量同步,否則進行全量同步。(從節點執行 psync
,master 返回 FULLRESYNC runid offset
進行全量同步,CONTINUE
進行增量同步)
更多詳細資料參考: