Redis 哨兵(Sentinel)
在生產過程當中,咱們會遇到主master從slave切換,當主(master)服務器出現redis服務器異常,主機斷電,磁盤損壞,等問題時候後,而redis主從複製沒法實現自動的故障轉移(將slave 自動提高爲新
master),須要手動把一臺從服務器切換爲主服務器,這個步驟須要人工切換,費時費力,還有可能形成"事故",另外也沒法橫向擴展Redis服務的並行寫入性能,當單臺Redis服務器性能沒法知足業務寫入需求的時候,也須要解決以上的兩個核心問題因此這個時候咱們會哨兵模式幫咱們解決,從而幫助咱們實現多臺服務器並行寫入已實現更高的併發問題的目的.
redis
下面咱們咱們介紹下算法
哨兵(Sentinel)工做原理概述
sentinel 架構和故障轉移
vim
Sentinel 進程是用於監控redis集羣中Master主服務器工做的狀態,在Master主服務器發生故障的時候,能夠實現Master和Slave服務器的切換,保證系統的高可用,此功能在redis2.6+的版本已引用,Redis的哨兵模式到了2.8版本以後就穩定了下來。通常在生產環境也建議使用Redis的2.8版本的之後版本centos
哨兵(Sentinel) 是一個分佈式系統,能夠在一個架構中運行多個哨兵(sentinel) 進程,這些進程使用流言協議(gossip protocols)來接收關於Master主服務器是否下線的信息,並使用投票協議(Agreement Protocols)來決定是否執行自動故障遷移,以及選擇哪一個Slave做爲新的Masterbash
每一個哨兵(Sentinel)進程會向其它哨兵(Sentinel)、Master、Slave定時發送消息,以確認對方是否」活」着,若是發現對方在指定配置時間(此項可配置)內未獲得迴應,則暫時認爲對方已離線,也就是所謂的」主觀認爲宕機」 (主觀:是每一個成員都具備的獨自的並且可能相同也可能不一樣的意識),英文名稱:Subjective Down,簡稱SDOWN服務器
主觀下線和客觀下線架構
有主觀宕機,對應的有客觀宕機。當「哨兵羣」中的多數Sentinel進程在對Master主服務器作出SDOWN的判斷,而且經過 SENTINEL is-master-down-by-addr 命令互相交流以後,得出的Master Server下線判斷,這種方式就是「客觀宕機」(客觀:是不依賴於某種意識而已經實際存在的一切事物),英文名稱是:Objectively Down, 簡稱 ODOWN併發
- 當一個主服務器被斷定爲客觀下線之後,監視這個服務器的各個Sentinel會進行協商,選舉出一個領頭的Sentinel,並由領頭Sentinel對下線主服務器進行故障轉移。
- 每通過一次選舉,不管選舉成功仍是失敗,每隔sentinel實例的配置紀元都會自增1,每一個新的紀元中,任何一個sentinel都有可能成爲領頭Sentinel。
經過必定的vote算法,從剩下的slave從服務器節點中,選一臺提高爲Master服務器節點,而後自動修改相關配置,並開啓故障轉移(failover)app
Sentinel 機制能夠解決master和slave角色的自動切換問題,但單個 Master 的性能瓶頸問題沒法解決,相似於MySQL中的MHA功能運維
注意事項:
- Redis Sentinel中的Sentinel節點個數應該爲大於等於3且最好爲奇數
- 客戶端初始化時鏈接的是Sentinel節點集合,再也不是具體的Redis節點,但Sentinel只是配置中心不是代理
- Redis Sentinel 節點與普通redis 沒有區別,要實現讀寫分離依賴於客戶端程序
- redis 3.0 以前版本中,生產環境通常使用哨兵模式,但3.0後推出redis cluster功能後,能夠支持更大規模的生產環境
sentinel中的三個定時任務
-
第一個定時
-
每10秒每一個sentinel對master和slave執行info
-
- 發現slave節點
- 確認主從關係
-
第二個定時
-
每2秒每一個sentinel經過master節點的channel交換信息(pub/sub)
-
- 經過sentinel__:hello頻道交互
- 交互對節點的「見解」和自身信息
-
第三個定時
-
每1秒每一個sentinel對其餘sentinel和redis執行ping
心跳檢測,失敗斷定的依據
如何實現哨兵
注意哨兵的準備實現主從複製架構
哨兵的前提是已經實現了一個redis的主從複製的運行環境,從而實現一個一主兩從基於哨兵的高可用redis架構
注意: master 的配置文件中masterauth 和slave 都必須相同
master和slave同步過程
一、從節點主動向主節點發送同步請求
二、主節點接收到從的消息後發送本身的runid和offset發送給從節點
三、從節點保存主節點發送過來的runid和offset
四、主節點後臺執行RDB持久化,並將新寫入的數據寫入到緩衝區中
五、主節點將RDB文件發送到從節點
六、主節點在把RDB文件發送到從節點後,把buffer中的數據以redis協議格式發送到從節點
七、從節點清空本身舊的數據
八、從節點把主節點推送過來的RDB文件中的數據載入內存,再加載全部緩衝區中的內容完成全量同步
九、全量同步完成後,如從節點須要繼續同步增量數據的話,會先將本身的offset位置發送給主節點,主節點在收到後會根據從節點的offset,將從節點offset位置以後的數據發送回從節點,同時也將在緩衝區的數據也發送給從節點
全部主從節點的redis.conf中關健配置
實踐範例:
#在全部主從節點執行 [root@centos8 ~]#dnf -y install redis [root@centos8 ~]#vim /etc/redis.conf bind 0.0.0.0 masterauth "123456" requirepass "123456" #或者非交互執行 [root@centos8 ~]#sed -i -e 's/bind 127.0.0.1/bind 0.0.0.0/' -e 's/^# masterauth .*/masterauth 123456/' -e 's/^# requirepass .*/requirepass 123456/' /etc/redis.conf #在全部從節點執行 [root@centos8 ~]#echo "replicaof 10.0.0.8 6379" >> /etc/redis.conf #在全部主從節點執行 [root@centos8 ~]#systemctl enable --now redis
master服務器狀態
[root@redis-master ~]#redis-cli -a 123456 Warning: Using a password with '-a' or '-u' option on the command line interface may not 127.0.0.1:6379> INFO replication # Replication role:master connected_slaves:2 slave0:ip=10.0.0.28,port=6379,state=online,offset=112,lag=1 slave1:ip=10.0.0.18,port=6379,state=online,offset=112,lag=0 master_replid:8fdca730a2ae48fb9c8b7e739dcd2efcc76794f3 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:112 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:112 127.0.0.1:6379>
配置slave1
[root@redis-slave1 ~]#redis-cli -a 123456 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> REPLICAOF 10.0.0.8 6379 OK 127.0.0.1:6379> CONFIG SET masterauth "123456" OK 127.0.0.1:6379> INFO replication # Replication role:slave master_host:10.0.0.8 master_port:6379 master_link_status:up master_last_io_seconds_ago:4 master_sync_in_progress:0 slave_repl_offset:140 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:8fdca730a2ae48fb9c8b7e739dcd2efcc76794f3 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:140 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_
配置slave2
[root@redis-slave2 ~]#redis-cli -a 123456 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> REPLICAOF 10.0.0.8 6379 OK 127.0.0.1:6379> CONFIG SET masterauth "123456" OK 127.0.0.1:6379> INFO replication # Replication role:slave master_host:10.0.0.8 master_port:6379 master_link_status:up master_last_io_seconds_ago:3 master_sync_in_progress:0 slave_repl_offset:182 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:8fdca730a2ae48fb9c8b7e739dcd2efcc76794f3 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:182 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:15 repl_backlog_histlen:168 127.0.0.1:6379>
編輯哨兵的配置文件
sentinel配置
- Sentinel其實是一個特殊的redis服務器,有些redis指令支持,但不少指令並不支持.默認監聽在26379/tcp端口.
- 哨兵能夠不和Redis服務器部署在一塊兒,但通常部署在一塊兒,全部redis節點使用相同的如下示例的配置文件
#若是是編譯安裝,在源碼目錄有sentinel.conf,複製到安裝目錄便可, 如:/apps/redis/etc/sentinel.conf [root@centos8 ~]#vim /etc/redis-sentinel.conf bind 0.0.0.0 port 26379 daemonize yes pidfile "redis-sentinel.pid" logfile "sentinel_26379.log" dir "/tmp" #工做目錄 sentinel monitor mymaster 10.0.0.8 6379 2 #指定當前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 sentinel parallel-syncs mymaster 1 #發生故障轉移後,同時向新master同步數據的slave數量,數字越小總同步時間越長,但能夠減輕新master的負載壓力 sentinel failover-timeout mymaster 180000 #全部slaves指向新的master所需的超時時間,單位:毫秒 sentinel deny-scripts-reconfig yes #禁止修改腳本 logfile /var/log/redis/sentinel.log
三個哨兵服務器的配置都以下
[root@redis-master ~]#grep -vE "^#|^$" /etc/redis-sentinel.conf port 26379 daemonize no pidfile "/var/run/redis-sentinel.pid" logfile "/var/log/redis/sentinel.log" dir "/tmp" sentinel monitor mymaster 10.0.0.8 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 #如下內容自動生成,不須要修改 sentinel myid 50547f34ed71fd48c197924969937e738a39975b #此行自動生成必須惟一,修改此 值需重啓redis和sentinel服務 ..... # Generated by CONFIG REWRITE protected-mode no supervised systemd sentinel leader-epoch mymaster 0 sentinel known-replica mymaster 10.0.0.28 6379 sentinel known-replica mymaster 10.0.0.18 6379 sentinel current-epoch 0 [root@redis-master ~]#scp /etc/redis-sentinel.conf redis-slave1:/etc/ [root@redis-master ~]#scp /etc/redis-sentinel.conf redis-slave2:/etc/
啓動哨兵
三臺哨兵服務器都要啓動
#確保每一個哨兵主機myid不一樣 [root@redis-slave1 ~]#vim /etc/redis-sentinel.conf sentinel myid 50547f34ed71fd48c197924969937e738a39975c [root@redis-slave2 ~]#vim /etc/redis-sentinel.conf sentinel myid 50547f34ed71fd48c197924969937e738a39975d [root@redis-master ~]#systemctl enable --now redis-sentinel.service [root@redis-slave1 ~]#systemctl enable --now redis-sentinel.service [root@redis-slave2 ~]#systemctl enable --now redis-sentinel.service
若是是編譯安裝,在全部哨兵服務器執行下面操做啓動哨兵
#vim /apps/redis/etc/sentinel.conf bind 0.0.0.0 port 26379 daemonize yes pidfile "redis-sentinel.pid" Logfile "sentinel_26379.log" dir "/apps/redis/data" sentinel monitor mymaster 10.0.0.8 6379 2 sentinel auth-pass mymaster 123456 sentinel down-after-milliseconds mymaster 15000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 sentinel deny-scripts-reconfig yes #/apps/redis/bin/redis-sentinel /apps/redis/etc/sentinel.conf
驗證哨兵端口
[root@redis-master ~]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 128 0.0.0.0:26379 0.0.0.0:* LISTEN 0 128 0.0.0.0:6379 0.0.0.0:* LISTEN 0 128 [::]:22 [::]:* LISTEN 0 128 [::]:26379 [::]:* LISTEN 0 128 [::]:6379 [::]:*
查看哨兵日誌
master的哨兵日誌
[root@redis-master ~]#tail -f /var/log/redis/sentinel.log 38028:X 20 Feb 2020 17:13:08.702 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 38028:X 20 Feb 2020 17:13:08.702 # Redis version=5.0.3, bits=64, commit=00000000, modified=0, pid=38028, just started 38028:X 20 Feb 2020 17:13:08.702 # Configuration loaded 38028:X 20 Feb 2020 17:13:08.702 * supervised by systemd, will signal readiness 38028:X 20 Feb 2020 17:13:08.703 * Running mode=sentinel, port=26379. 38028:X 20 Feb 2020 17:13:08.703 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. 38028:X 20 Feb 2020 17:13:08.704 # Sentinel ID is 50547f34ed71fd48c197924969937e738a39975b 38028:X 20 Feb 2020 17:13:08.704 # +monitor master mymaster 10.0.0.8 6379 quorum 2 38028:X 20 Feb 2020 17:13:08.709 * +slave slave 10.0.0.28:6379 10.0.0.28 6379 @ mymaster 10.0.0.8 6379 38028:X 20 Feb 2020 17:13:08.709 * +slave slave 10.0.0.18:6379 10.0.0.18 6379 @ mymaster 10.0.0.8 6379
slave的哨兵日誌
root@redis-slave1 ~]#tail -f /var/log/redis/sentinel.log 25509:X 20 Feb 2020 17:13:27.435 * Removing the pid file. 25509:X 20 Feb 2020 17:13:27.435 # Sentinel is now ready to exit, bye bye... 25572:X 20 Feb 2020 17:13:27.448 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 25572:X 20 Feb 2020 17:13:27.448 # Redis version=5.0.3, bits=64, commit=00000000, modified=0, pid=25572, just started 25572:X 20 Feb 2020 17:13:27.448 # Configuration loaded 25572:X 20 Feb 2020 17:13:27.448 * supervised by systemd, will signal readiness 25572:X 20 Feb 2020 17:13:27.449 * Running mode=sentinel, port=26379. 25572:X 20 Feb 2020 17:13:27.449 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. 25572:X 20 Feb 2020 17:13:27.449 # Sentinel ID is 50547f34ed71fd48c197924969937e738a39975b 25572:X 20 Feb 2020 17:13:27.449 # +monitor master mymaster 10.0.0.8 6379 quorum2
當前sentinel狀態
在sentinel狀態中尤爲是最後一行,涉及到masterIP是多少,有幾個slave,有幾個sentinels,必須是符合所有服務器數量
[root@redis-master ~]#redis-cli -p 26379 127.0.0.1:26379> INFO sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=10.0.0.8:6379,slaves=2,sentinels=3 #兩個 slave,三個sentinel服務器,若是sentinels值不符合,檢查myid可能衝突
中止Redis Master測試故障轉移
[root@redis-master ~]#killall redis-server
查看各節點上哨兵信息:
[root@redis-master ~]#redis-cli -a 123456 -p 26379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:26379> INFO sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=10.0.0.18:6379,slaves=2,sentinels=2