雖然Redis可以實現單機的數據持久化,但無論是RDB也好或者AOF也好,都解決不了單點宕機問題,即一旦單臺 redis服務器本身出現系統故障、硬件故障等問題后,就會直接造成數據的丟失
此外,單機的性能也是有極限的,因此需要使用另外的技術來解決單點故障和性能擴展的問題。
一.redis主從復制
1.redis 主從復制架構
主從模式(master/slave),可以實現Redis數據的跨主機備份。
程序端連接到高可用負載的VIP,然后連接到負載服務器設置的Redis后端real server,此模式不需要在程序里面配 置Redis服務器的真實IP地址,當后期Redis服務器IP地址發生變更只需要更改redis 相應的后端real server即可, 可避免更改程序中的IP地址設置。
2.主從復制特點
-
一個master可以有多個slave
-
一個slave只能有一個master
-
數據流向是從master到slave單向的
3.主從復制的基本原理
配置設置:
主節點(Master):配置允許從節點連接,并記錄所有數據變更(寫操作)。
從節點(Slave):配置連接到主節點,并接收主節點發送的數據副本。復制流程:
主節點持續記錄執行的寫操作(包括SET、DEL等),并將這些寫操作以命令的形式發送給所有連接的從節點。
從節點接收到這些命令并執行,以確保其數據與主節點保持同步。初始化同步:
新的從節點在連接到主節點時,可以選擇全量復制(將主節點的所有數據復制一份到從節點)或者部分復制(只復制從連接后的數據變更)。
心跳檢測和重連:
主從節點之間通過心跳機制保持連接。如果從節點與主節點斷開連接,它會嘗試重新連接并請求同步缺失的數據。
讀寫分離:
從節點可以用于處理只讀操作,以減輕主節點的負載。客戶端可以選擇性地連接到從節點進行讀取操作,從而分擔主節點的讀取壓力。
當配置Redis復制功能時,強烈建議打開主服務器的持久化功能。否則的話,由于延遲等問題,部署的主節點Redis服務應該要避免自動啟動。
參考案例: 導致主從服務器數據全部丟失
1.假設節點A為主服務器,并且關閉了持久化。并且節點B和節點c從節點A復制數據
2.節點A崩潰,然后由自動拉起服務重啟了節點A.由于節點A的持久化被關閉了,所以重啟之后沒有任何數據
3.節點B和節點c將從節點A復制數據,但是A的數據是空的,于是就把自身保存的數據副本刪除。
在關閉主服務器上的持久化,并同時開啟自動拉起進程的情況下,即便使用Sentinel來實現Redis的高可用性,也是非常危險的。因為主服務器可能拉起得非常快,以至于Sentinel在配置的心跳時間間隔內沒有檢測到主服務器已被重啟,然后還是會執行上面的數據丟失的流程。無論何時,數據安全都是極其重要的,所以應該禁止主服務器關閉持久化的同時自動啟動。
4.命令行配置
命令 | 解釋 |
---|---|
info replication | 查看主從狀態 |
repliacaof | 添加主從配置 例子: repliacaof 192.168.91.100 6379 |
CONFIG SET masterauth 123456 | 設置密碼 |
REPLICAOF no one | 取消 主從配置 |
5.實現主從復制
主服務器:192.168.240.13
[root@localhost ~]#vim /etc/redis/6379.conf
70 bind 0.0.0.0
#將監聽端口改為任意端口
requirepass 12345
#設置密碼
172 logfile /var/log/redis_6379.log
#指定日志文件目錄
264 dir /var/lib/redis/6379
#指定工作目錄
700 appendonly yes
#開啟AOF持久化功能
從服務器:192.168.240.14??
#安裝redis略
#修改配置文件70 bind 0.0.0.0
#將監聽端口改為任意端口
172 logfile /var/log/redis_6379.log
#指定日志文件目錄
264 dir /var/lib/redis/6379
#指定工作目錄
288 replicaof 192.168.91.100 6379
#設置 主從配置
masterauth 123456
#如果有密碼 設置此行700 appendonly yes
#開啟AOF持久化功能
5.1關閉防火墻和selinux
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0
5.2 進入從的配置文件?
replicaof 192.168.240.13 6379#主服務器地址 #端口號
如果需要添加密碼,在主服務器配置文件中添加密碼
requirepass a
在從服務器配置文件中加入
masterauth a
5.3 重新啟動從服務器,并進入redis數據庫查看主從狀態
slave 狀態只讀無法寫入數據
systemctl restart redis
redis-cli
127.0.0.1:6379> info replication
從服務器?
role:slave
表示當前 Redis 服務器的角色是從服務器。master_host:192.168.240.13
指定當前從服務器正在復制的主服務器的 IP 地址。master_port:6379
指定當前從服務器正在復制的主服務器的端口號。master_link_status:up
表示從服務器與主服務器之間的連接狀態為正常(連接已建立)。master_last_io_seconds_ago:8
指示從服務器上次與主服務器進行通信的時間,單位為秒,這里表示距離上次通信已經過去了8秒。master_sync_in_progress:0
表示當前沒有正在進行中的主從同步操作。slave_repl_offset:24865
指示從服務器當前的復制偏移量,即從主服務器已經復制到的數據量。slave_priority:100
從服務器的復制優先級,這里設置為100,表示當前從服務器在進行故障轉移時的優先級。slave_read_only:1
表示從服務器是否設置為只讀模式,這里設置為1,表示從服務器不接受寫操作。connected_slaves:0
指示當前連接到該從服務器的從服務器數量,這里為0,表示該從服務器沒有其他從服務器連接。master_replid:9c941d96163ba330053c1cb212c8ab5af806adb4
主服務器的復制 ID,用于標識主服務器的唯一標識符。master_replid2:0000000000000000000000000000000000000000
輔助用于復制的 ID,通常為 40 個零,表示在執行故障轉移時用作附加標識。master_repl_offset:24865
主服務器的復制偏移量,表示當前主服務器已經復制給從服務器的數據量。second_repl_offset:-1
第二個復制偏移量,通常不使用,這里值為 -1。repl_backlog_active:1
表示復制后備日志(replication backlog)是否處于活動狀態(active),即是否正在使用。repl_backlog_size:1048576
復制后備日志的大小,這里為 1048576 字節(1 MB),表示可用于復制的最大歷史數據量。repl_backlog_first_byte_offset:24796
復制后備日志的第一個字節的偏移量,表示第一個有效數據在復制后備日志中的位置。repl_backlog_histlen:70
復制后備日志的歷史長度,表示當前復制后備日志中存儲的歷史數據條目數。
主服務器
role:master#表示當前 Redis 服務器的角色是主服務器。
connected_slaves:1#表示當前連接的從服務器數量,這里有一個從服務器連接到了主服務器。
slave0:ip=192.168.240.14,port=6379,state=online,offset=24935,lag=1#描述了從服務器的詳細信息:ip=192.168.240.14,port=6379:從服務器的 IP 地址和端口號。state=online:從服務器的狀態,這里是在線狀態。offset=24935:從服務器當前復制的偏移量(offset),即從主服務器同步的數據偏移量。lag=1:從服務器與主服務器的復制延遲,即從服務器在處理復制數據時的滯后量(以秒為單位)。
master_replid:9c941d96163ba330053c1cb212c8ab5af806adb4#主服務器的復制 ID,用于標識主服務器的唯一標識符。
master_replid2:0000000000000000000000000000000000000000#輔助用于復制的 ID,通常為 40 個零,表示在執行故障轉移時用作附加標識。
master_repl_offset:24935#主服務器的復制偏移量,表示當前主服務器已經復制給從服務器的數據量。
second_repl_offset:-1#第二個復制偏移量,通常不使用,這里值為 -1。
repl_backlog_active:1#表示復制后備日志(replication backlog)是否處于活動狀態(active),即是否正在使用。
repl_backlog_size:1048576#復制后備日志的大小,這里為 1048576 字節(1 MB),表示可用于復制的最大歷史數據量。
repl_backlog_first_byte_offset:24796#復制后備日志的第一個字節的偏移量,表示第一個有效數據在復制后備日志中的位置。
repl_backlog_histlen:140#復制后備日志的歷史長度,表示當前復制后備日志中存儲的歷史數據條目數。
測試:
6.刪除主從復制
在從服務器執行 REPLIATOF NO ONE 指令可以取消主從復制
#取消復制,在slave上執行REPLIATOF NO ONE,會斷開和master的連接不再主從復制, 但不會清除slave
上已有的數據
127.0.0.1:6379> REPLICAOF no one
7.主從復制故障恢復
master故障后,只能手動提升一個slave為新master,不支持自動切換。
之后將其它的slave節點重新指定新的master為master節點
Master的切換會導致master_replid發生變化,slave之前的master_replid就和當前master不一致從而會引發所有 slave的全量同步。
8.主從復制完整過程
1)從服務器連接主服務器,發送PSYNC命令
2)主服務器接收到PSYNC命令后,開始執行BGSAVE命令生成RDB快照文件并使用緩沖區記錄此后執行的所有
寫命令
3)主服務器BGSAVE執行完后,向所有從服務器發送RDB快照文件,并在發送期間繼續記錄被執行的寫命令
4)從服務器收到快照文件后丟棄所有舊數據,載入收到的快照至內存
5)主服務器快照發送完畢后,開始向從服務器發送緩沖區中的寫命令
6)從服務器完成對快照的載入,開始接收命令請求,并執行來自主服務器緩沖區的寫命令
7)后期同步會先發送自己slave_repl_offset位置,只同步新增加的數據,不再全量同步
復制緩沖區配置參數
#復制緩沖區大小,建議要設置足夠大
repl-backlog-size 1mb #Redis同時也提供了當沒有slave需要同步的時候,多久可以釋放環形隊列:
repl-backlog-ttl ? 3600
9.主從同步優化配置
Redis在2.8版本之前沒有提供增量部分復制的功能,當網絡閃斷或者slave Redis重啟之后會導致主從之間的全量同步,即從2.8版本開始增加了部分復制的功能。
repl-diskless-sync:
功能: 控制是否使用無盤同步 RDB 文件。當設置為?yes
?時,主服務器不會將 RDB 文件保存到磁盤上,而是直接通過 socket 文件發送給從服務器。
建議配置: 根據實際情況選擇,如果希望減少磁盤 I/O 操作并且網絡條件良好,可以考慮設置為?yes
。repl-diskless-sync-delay:
功能: 在使用無盤同步時,從服務器等待接收 RDB 數據的時間延遲。
建議配置: 默認值為 5 秒通常是一個合理的設置,可以根據網絡延遲和從服務器的性能調整。repl-ping-slave-period:
功能: 從服務器向主服務器發送 ping 的時間間隔,用于保持連接。
建議配置: 默認值為 10 秒通常是合適的,可以根據網絡穩定性調整,不建議設置得太短以避免過多的網絡開銷。repl-timeout:
功能: 設置主從連接的超時時間,超過此時間沒有收到響應將認為連接斷開。
建議配置: 默認值為 60 秒通常是合適的,可以根據網絡環境和延遲進行微調。repl-disable-tcp-nodelay:
功能: 控制是否啟用 TCP_NODELAY。啟用后可以減少網絡帶寬消耗,但可能會增加同步延遲。
建議配置: 根據數據的一致性要求和網絡性能進行選擇。通常選擇?no
,以確保數據同步的及時性和準確性。repl-backlog-size:
功能: 主服務器用于保存復制數據的寫入緩沖區大小。
建議配置: 根據從服務器斷開連接后能容忍的最長時間和主服務器的寫入速率來設置。建議按照需求調整,確保足夠的緩沖區來支持斷線重連時的數據傳輸。repl-backlog-ttl:
功能: 如果一段時間后沒有從服務器連接到主服務器,定義主服務器寫入緩沖區的超時時間。建議配置: 根據系統的需求設置合適的時間,以免長時間未使用的資源占用內存。slave-priority:
功能: 設置從服務器的優先級,用于在主服務器故障后選舉新的主服務器。
建議配置: 如果有多個從服務器,可以設置不同的優先級以影響選舉結果。min-replicas-to-write:
功能: 設置主服務器至少需要多少個可用從服務器,否則拒絕執行寫操作。
建議配置: 根據系統的容錯需求進行設置,確保即使部分從服務器不可用也能保持系統的可寫性。min-slaves-max-lag:
功能: 當從服務器的復制延遲超過設定值時,主服務器不再接受寫操作。
建議配置: 根據系統的性能和復制鏈路的穩定性設置合適的延遲閾值,以避免數據不一致性問題。
二.哨兵模式(Sentinel)
edis 哨兵模式是一種用于高可用性(High Availability, HA)的解決方案,它允許 Redis 在主從復制的基礎上,提供自動故障恢復和故障轉移的功能。主要用途是監控 Redis 實例,并在主節點失效時自動將一個從節點晉升為新的主節點,以保證服務的持續可用性。
1.主要組件和概念
哨兵(Sentinel):
哨兵是一個運行在獨立進程中的程序,其主要任務是監控 Redis 實例的狀態(主節點和從節點),并在主節點失效時執行自動故障轉移。
主節點(Master):
Redis 中的主節點負責接收寫操作,并將數據同步到所有從節點。
從節點(Slave):
從節點是主節點的復制品,它們復制主節點的數據,并在需要時可以晉升為新的主節點。
2.哨兵模式的工作原理
哨兵模式包括多個哨兵進程和多個 Redis 節點(主節點和從節點)。哨兵進程定期檢查 Redis 實例的健康狀態,并在發現故障時采取自動化的措施。
監控:
每個哨兵進程會定期檢查監控的 Redis 實例的健康狀態,包括主節點和從節點。
故障檢測:
如果一個哨兵進程發現主節點不可用(比如網絡故障、進程崩潰等),它會開始執行一系列故障檢測步驟,以確保主節點確實不可用。
選舉新主節點:
當主節點被確認為不可用時,哨兵會通過一種投票機制選舉一個從節點作為新的主節點。這個過程會考慮每個哨兵的優先級和配置,確保選舉出的主節點具有一致性和可靠性。
故障轉移:
一旦新的主節點被選出,哨兵會協調所有的 Redis 客戶端和其他哨兵,使它們知道新的主節點的位置。這個過程稱為故障轉移(failover),通常會在幾秒鐘內完成。
配置同步:
新的主節點上任后,哨兵還會確保所有從節點正確地重新配置為新的主節點的從節點,并開始從新的主節點同步數據。
3.優點和適用場景
-
自動化的高可用性:哨兵模式使得 Redis 集群在主節點故障時可以自動化地完成故障轉移,減少了人工介入和服務中斷的可能性。
-
實時監控和通知:哨兵可以實時監控 Redis 的健康狀況,并在必要時通過警報或通知管理員進行干預。
-
簡化擴展和維護:通過自動處理故障轉移,哨兵模式簡化了 Redis 集群的擴展和維護工作。
4.實現哨兵模式
哨兵的前提是已經實現了一個redis的主從復制的運行環境,從而實現一個一主兩從基于哨兵的高可用
redis架構
注意: master 的配置文件中masterauth 和slave 都必須相同
所有主從節點的redis.conf中關健配置
主服務器:192.168.240.13 端口:6379? 哨兵1
從服務器1:192.168.240.14 端口:6379 哨兵2
從服務器2:192.168.240.12 端口:6379 哨兵3
1)關閉防火墻關閉selinux
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0
2)配置主從復制
3)編輯哨兵的配置文件
sentinel配置
Sentinel實際上是一個特殊的redis服務器,有些redis指令支持,但很多指令并不支持.默認監聽在26379/tcp端口.
哨兵可以不和Redis服務器部署在一起,但一般部署在一起以節約成本
所有redis節點使用相同的以下示例的配置文件
[root@localhost redis-5.0.7]# cp sentinel.conf /apps/redis/etc/
[root@localhost redis-5.0.7]# vim /apps/redis/etc/sentinel.conf
bind 0.0.0.0 #修改監聽端口
port 26379 #不用修改默認
daemonize yes # 不用修改如果是systemd 啟動模式, 修改后啟動不了
pidfile "/apps/resdis/run/redis-sentinel.pid" #指定pid文件
logfile "/apps/redis/log/sentinel_26379.log" # 指定日志文件
dir "/tmp" ?#工作目錄不用修改sentinel monitor mymaster 10.0.0.8 6379 2
#mymaster是集群的名稱,此行指定當前mymaster集群中master服務器的地址和端口
#2為法定人數限制(quorum),即有幾個sentinel認為master down了就進行故障轉移,一般此值是所有sentinel節點(一般總數是>=3的 奇數,如:3,5,7等)的一半以上的整數值,比如,總數是3,即3/2=1.5,取整為2,是master的ODOWN客觀下線的依據sentinel auth-pass mymaster 123456
#mymaster集群中master的密碼,注意此行要在上面行的下面sentinel down-after-milliseconds mymaster 30000
#(SDOWN)判斷mymaster集群中所有節點的主觀下線的時間, 單位:毫秒,建議3000(3秒) 否則等待時間過長sentinel parallel-syncs mymaster 1
#發生故障轉移后,可以同時向新master同步數據的slave的數量,數字越小總同步時間越長,但可以減輕新master的負載壓力sentinel failover-timeout mymaster 180000
#所有slaves指向新的master所需的超時時間,單位:毫秒sentinel deny-scripts-reconfig yes #禁止修改腳本
?修改文件的內容
[root@localhost etc]#grep -vE "^#|^$" sentinel.conf
bind 0.0.0.0
port 26379
daemonize yes
pidfile /apps/redis/run/redis-sentinel.pid
logfile "/apps/redis/log/sentinel.log"
dir /tmp
sentinel monitor mymaster 192.168.240.13 6379 2
sentinel auth-pass mymaster 123456
sentinel down-after-milliseconds mymaster 3000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
4)準備service 文件 注意先開 主再開從 全部節點都需要
cat >> /lib/systemd/system/redis-sentinel.service <<eof
[Unit]
Description=Redis Sentinel
After=network.target
[Service]
ExecStart=/apps/redis/bin/redis-sentinel /apps/redis/etc/sentinel.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
eof
[root@localhost etc]# systemctl daemon-reload
[root@localhost etc]# systemctl start redis-sentinel.service
5)將主服務器上的sentinel.conf傳輸到兩臺從服務器
scp -r /apps/redis/etc/sentinel.conf 192.168.240.14://apps/redis/etc/
scp -r /apps/redis/etc/sentinel.conf 192.168.240.12://apps/redis/etc/
6)將所有節點上的sentinel.conf文件權限屬主屬組改為redis
[root@localhost ~]# cd /apps/redis/etc/
[root@localhost etc]# ls
redis.conf sentinel.conf
[root@localhost etc]# chown redis.redis sentinel.conf
[root@localhost etc]# ll
總用量 76
-rw-r--r--. 1 redis redis 61857 7月 9 16:09 redis.conf
-rw-r--r--. 1 redis redis 9804 7月 10 17:48 sentinel.conf
7)刷新配置文件,先開啟主上的哨兵在開啟從
[root@localhost etc]# systemctl daemon-reload
[root@localhost etc]# systemctl start redis-sentinel.service
[root@localhost etc]# systemctl status redis-sentinel.service
8)主從服務器上查看日志文件
tail -f /apps/redis/log/sentinel.log
ss -natp |grep 26379
主服務器
?
從服務器?
9)測試,關閉主服務器redis
systemctl stop redis
查看日志
主服務器
從服務器1成為新的主服務器
從服務器1
從服務器1成為新的主服務器
從服務器2
從服務器1成為新的主服務器,從2指向新主
當再次開啟原主服務器時
這是不會搶占主的位置會成為新主的從服務器