Redis 主從復制
- Redis 主從復制
- 1. Redis 主從復制架構
- 2. 主從復制實現
- 2.1 主從命令配置
- 2.1.1 啟用主從同步
- 2.1.2 查看日志觀察同步狀態
- 2.1.3 修改 Slave 節點配置文件
- 2.1.4 刪除主從同步
- 3. 主從復制故障恢復
- 3.1 Slave 節點故障和恢復
- 3.2 Master 節點故障和恢復
- 3.3 常見主從復制故障
- 4. 主從復制優化
- 4.1 避免全量復制
- 4.2 避免復制風暴
- 4.3 性能相關配置
Redis 主從復制
Redis單機服務存在數據和服務的單點問題,而且單機性能也存在著上限,可以利用Redis的集群相關技術來解決這些問題
1. Redis 主從復制架構
Redis和MySQL的主從模式類似,也支持主從模式(master/slave),可以實現Redis數據的跨主機的遠程備份
常見客戶端連接主從的架構:
程序APP先連接到高可用性 LB 集群提供的虛擬IP,再由LB調度將用戶的請求至后端Redis 服務器來真正提供服務
主從復制特點
- 一個master可以有多個slave
- 一個slave只能有一個master
- 數據流向是從master到slave單向的
- master 可讀可寫 slave 只讀
2. 主從復制實現
當master出現故障后,可以自動提升一個slave節點變成新的Mster,因此Redis Slave 需要設置和master相同的連接密碼
此外當一個Slave提升為新的master時需要通過持久化實現數據的恢復
當配置Redis復制功能時,強烈建議打開主服務器的持久化功能。否則的話,由于延遲等問題,部署的主節點Redis服務應該要避免自動啟動
導致主從服務器數據全部丟失
- 假設節點A為主服務器,并且關閉了持久化。并且節點B和節點C從節點A復制數據
- 節點A崩潰,然后由自動拉起服務重啟了節點A,由于節點A的持久化被關閉了,所以重啟之后沒有任何數據
- 節點B和節點C將從節點A復制數據,但是A的數據是空的,于是就把自身保存的數據副本刪除。
在關閉主服務器上的持久化,并同時開啟自動拉起進程的情況下,即便使用Sentinel來實現Redis的高可用性,也是非常危險的。因為主服務器可能拉起得非常快,以至于Sentinel在配置的心跳時間間隔內沒有檢測到主服務器已被重啟,然后還是會發生上面描述的情況,導致數據丟失
無論何時,數據安全都是極其重要的,所以應該禁止主服務器關閉持久化的同時自動啟動
主從復制過程
Redis主從復制分為全量同步和增量同步
Redis 的主從同步是非阻塞的,即同步過程不會影響主服務器的正常訪問
注意:主節點重啟會導致全量同步,從節點重啟只會導致增量同步
全量復制過程 Full resync
- 主從節點建立連接,驗證身份后,從節點向主節點發送PSYNC(2.8版本之前是SYNC)命令
- 主節點向從節點發送FULLRESYNC命令,包括master_replid(runID)和offset
- 從節點保存主節點信息
- 主節點執行BGSAVE保存RDB文件,同時記錄新的記錄到buffer中
- 主節點發送RDB文件給從節點
- 主節點將新收到buffer中的記錄發送至從節點
- 從節點刪除本機的舊數據
- 從節點加載RDB
- 從節點同步主節點的buffer信息
全量復制發生在下面情況
- 從節點首次連接主節點(無master_replid/run_id)
- 從節點的復制偏移量不在復制積壓緩沖區內
- 從節點無法連接主節點超過一定的時間
增量復制過程
在主從復制首次完成全量同步之后再次需要同步時,從服務器只要發送當前的offset位置(類似于MySQL的 binlog的位置)給主服務器,然后主服務器根據相應的位置將之后的數據(包括寫在緩沖區的積壓數據)發送給從服務器,再次將其保存到從節點內存即可。 即首次全量復制,之后的復制基本增量復制實現。
主從同步完整過程
- slave發起連接master,驗證通過后,發送PSYNC命令
- master接收到PSYNC命令后,執行BGSAVE命令將全部數據保存至RDB文件中,并將后續發生的寫操作記錄至buffer中
- master向所有slave發送RDB文件
- master向所有slave發送后續記錄在buffer中寫操作
- slave收到快照文件后丟棄所有舊數據
- slave加載收到的RDB到內存
- slave 執行來自master接收到的buffer寫操作
- 當slave完成全量復制后,后續master只會先發送slave_repl_offset信息
- 以后slave比較自身和master的差異,只會進行增量復制的數據即可
注意:Redis 重啟服務后,master_replid(runID)會發生變化。
復制緩沖區(環形隊列)配置參數
#master的寫入數據緩沖區,用于記錄自上一次同步后到下一次同步過程中間的寫入命令,計算公式:repl-backlog-size = 允許從節點最大中斷時長 * 主實例offset每秒寫入量,比如:master每秒最大寫入64mb,最大允許60秒,那么就要設置為64mb*60秒=3840MB(3.8G),建議此值是設置的足夠大,默認值為1M
repl-backlog-size 1mb #如果一段時間后沒有slave連接到master,則backlog size的內存將會被釋放。如果值為0則表示永遠不釋放這部份內存。
repl-backlog-ttl 3600
2.1 主從命令配置
2.1.1 啟用主從同步
Redis Server 默認為 master節點,如果要配置為從節點,需要指定master服務器的IP,端口及連接密碼
在從節點執行 REPLICAOF MASTER_IP PORT 指令可以啟用主從同步復制功能,早期版本使用 SLAVEOF 指令
127.0.0.1:6379> REPLICAOF MASTER_IP PORT #新版推薦使用
127.0.0.1:6379> SLAVEOF MasterIP Port #舊版使用,將被淘汰
127.0.0.1:6379> CONFIG SET masterauth <masterpass>
先通過一鍵編譯腳本在三臺主機上安裝好redis,搭建一主兩從
主機IP | 節點 |
---|---|
10.0.0.100 | 主 |
10.0.0.101 | 從 |
10.0.0.102 | 從 |
準備階段:
# 在mater上設置一些key方便觀察
[root@ubuntu2204 ~]#redis-cli -a 123456 info keyspace
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Keyspace
db0:keys=1000,expires=0,avg_ttl=0# 兩個從節點目前沒有key
[root@ubuntu2204 ~]#redis-cli -a 123456 info keyspace
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Keyspace# 三個節點默認都是master
[root@ubuntu2204 ~]#redis-cli -a 123456 info replication
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:b60b6478f2bb8d8a2e356b9d3c8540492e828708
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
具體搭建步驟:
# 兩個從節點都執行
[root@ubuntu2204 ~]#redis-cli -a 123456
# 在slave上設置master的IP和端口
127.0.0.1:6379> replicaof 10.0.0.100 6379
OK# 在slave上設置master的密碼,才可以同步
127.0.0.1:6379> config set masterauth 123456
OK# 查看是否成為slave
127.0.0.1:6379> info replication# 查看是否同步成功
127.0.0.1:6379> info keyspace
# Keyspace
db0:keys=1000,expires=0,avg_ttl=0# 主節點上查看
# 在master上可以看到所有slave信息
127.0.0.1:6379> info replication
2.1.2 查看日志觀察同步狀態
# 主從節點分別在同步之前打開日志觀察
[root@ubuntu2204 ~]#tail -f /apps/redis/log/redis_6379.log
2.1.3 修改 Slave 節點配置文件
[root@ubuntu2204 ~]#vim /apps/redis/etc/redis.conf(大約在533、540行附近)
replicaof 10.0.0.100 6379
masterauth 123456注意:requirepass 123456 的密碼要和masterauth保持一致,用于將來從節點提升主后使用。# 重啟redis服務
[root@ubuntu2204 ~]#systemctl restart redis# Master和Slave查看狀態
[root@ubuntu2204 ~]#redis-cli -a 123456
127.0.0.1:6379> info replication注意:
master_link_status:up
master_last_io_seconds_ago:6 # 如果主從復制通信正常,每10秒重新從0計數,此值無法修改,如果無法通信,當計數到60時,master_link_status顯示為down
master_sync_in_progress:0 # 0表示同步完成,1表示正在同步# 查看是否同步成功
127.0.0.1:6379> info keyspace
# Keyspace
db0:keys=1000,expires=0,avg_ttl=0# Slave 只讀狀態
127.0.0.1:6379> set key1 v1
(error) READONLY You can't write against a read only replica.
2.1.4 刪除主從同步
在從節點執行 REPLICAOF NO ONE 或 SLAVEOF NO ONE 指令可以取消主從復制
取消復制會斷開和master的連接而不再有主從復制關聯, 但不會清除slave上已有的數據
# 新版
127.0.0.1:6379> REPLICAOF NO ONE# 舊版
127.0.0.1:6379> SLAVEOF NO ONE
3. 主從復制故障恢復
3.1 Slave 節點故障和恢復
當 slave 節點故障時,將Redis Client指向另一個 slave 節點即可,并及時修復故障從節點
3.2 Master 節點故障和恢復
當 master 節點故障時,需要提升slave為新的master
master故障后,當前還只能手動提升一個slave為新master,不能自動切換。
之后將其它的slave節點重新指定新的master為master節點
Master的切換會導致master_replid發生變化,slave之前的master_replid就和當前master不一致從而會引發所有 slave的全量同步。
具體操作步驟:
1.查看當前節點的狀態為是否為slave,master指向是否是故障的master節點
2.停止slave同步并提升為新的master 使用命令 REPLICAOF NO ONE ,配置文件也要修改
3.修改所有slave 指向新的master節點使用命令 replicaof 新masterIP地址 6379 ,配置文件也要修改
4.在新master節點上查看狀態
3.3 常見主從復制故障
主從硬件和軟件配置不一致
主從節點的maxmemory不一致,主節點內存大于從節點內存,主從復制可能丟失數據
rename-command 命令不一致,如在主節點啟用flushdb,從節點禁用此命令,結果在master節點執行 flushdb后,導致slave節點不同步
Master 節點密碼錯誤
如果slave節點配置的master密碼錯誤,導致驗證不通過,自然將無法建立主從同步關系。
Redis 版本不一致
不同的redis 版本之間尤其是大版本間可能會存在兼容性問題,如:Redis 3,4,5,6之間
因此主從復制的所有節點應該使用相同的版本
安全模式下無法遠程連接
如果開啟了安全模式,并且沒有設置bind地址和密碼,會導致無法遠程連接
4. 主從復制優化
4.1 避免全量復制
- 第一次全量復制不可避免,后續的全量復制可以利用小主節點(內存小),業務低峰時進行全量
- 節點RUN_ID不匹配:主節點重啟會導致RUN_ID變化,可能會觸發全量復制,可以利用config命令動態修改配置,故障轉移例如哨兵或集群選舉新的主節點也不會全量復制,而從節點重啟動,不會導致全量復制,只會增量復制
- 復制積壓緩沖區不足: 當主節點生成的新數據大于緩沖區大小,從節點恢復和主節點連接后,會導致全量復制 解決方法將repl-backlog-size 調大
4.2 避免復制風暴
單主節點復制風暴
當主節點重啟,多從節點復制
解決方法:更換復制拓撲(級聯復制)
單機器多實例復制風暴
機器宕機后,大量全量復制
解決方法:主節點分散多機器
4.3 性能相關配置
Redis在2.8版本之前沒有提供增量部分復制的功能,當網絡閃斷或者slave Redis重啟之后會導致主從之間的全量同步,即從2.8版本開始增加了部分復制的功能。
repl-diskless-sync no # 是否使用無盤方式進行同步RDB文件,默認為no(編譯安裝默認為yes),no表示不使用無盤,需要將RDB文件保存到磁盤后再發送給slave,yes表示使用無盤,即RDB文件不需要保存至本地磁盤,而且直接通過網絡發送給slaverepl-diskless-sync-delay 5 # 無盤時復制的服務器等待的延遲時間repl-ping-slave-period 10 # slave向master發送ping指令的時間間隔,默認為10srepl-timeout 60 # 指定ping連接超時時間,超過此值無法連接,master_link_status顯示為down狀態,并記錄錯誤日志repl-disable-tcp-nodelay no # 是否啟用TCP_NODELAY
# 設置成yes,則redis會合并多個小的TCP包成一個大包再發送,此方式可以節省帶寬,但會造成同步延遲時長的增加,導致master與slave數據短期內不一致
# 設置成no,則master會立即同步數據repl-backlog-size 1mb # master的寫入數據緩沖區,用于記錄自上一次同步后到下一次同步前期間的寫入命令,計算公式:repl-backlog-size = 允許slave最大中斷時長 * master節點offset每秒寫入量,如:master每秒最大寫入量為32MB,最長允許中斷60秒,就要至少設置為32*60=1920MB,建議此值是設置的足夠大,如果此值太小,會造成全量復制repl-backlog-ttl 3600 # 指定多長時間后如果沒有slave連接到master,則backlog的內存數據將會過期。如果值為0表示永遠不過期。 slave-priority 100 # slave參與選舉新的master的優先級,此整數值越小則優先級越高。當master故障時將會按照優先級來選擇slave端進行選舉新的master,如果值設置為0,則表示該slave節點永遠不會被選為master節點。min-replicas-to-write 1 # 指定master的可用slave不能少于個數,如果少于此值,master將無法執行寫操作,默認為0,生產建議設為1,min-slaves-max-lag 20 # 指定至少有min-replicas-to-write數量的slave延遲時間都大于此秒數時,master將不能執行寫操作,默認為10s