1.引子
在之前的文章Redis的主從複制原理及docker環境下的實操中,實作了redis在docker環境下的主從複制,這時候會出現一個問題,如果Master挂了,如何保證可用性,實作繼續讀寫,這時候就需要使用哨兵對redis主從服務進行監控。
2.什麼是哨兵 sentinel
哨兵(Sentinel)是用于監控redis主從架構中master狀态狀态的工具,是redis高可用解決方案。哨兵可以監控一個或者多個redis master服務,以及這些master服務的所有slave服務。當某個master服務當機後,會把這個master下的某個從服務更新為master來替代以當機的master繼續工作。
Redis-Sentinel是Redis官方推薦的高可用性(HA)解決方案。實際上這意味着你可以使用Sentinel模式建立一個可以不用人為幹預而應對各種故障的Redis部署。
3.主要功能
- 監控:Sentinel不斷的檢查master和slave是否正常的運作。
- 通知:如果發現某個redis節點運作出現問題,可以通過API通知系統管理者和其他的應用程式。
- 自動故障轉移:能夠進行自動切換。當一個master節點不可用時,能夠選舉出master的多個slave中的一個來作為新的master,其它的slave節點會将它所追随的master的位址改為被提升為master的slave的新位址。
- 配置提供者:哨兵作為Redis用戶端發現的權威來源:用戶端連接配接到哨兵請求目前可靠的master的位址。如果發生故障,哨兵将報告新位址。
4.sentinel的分布式特性
很顯然,隻使用單個sentinel程序來監控redis叢集是不可靠的,當sentinel程序宕掉後(sentinel本身也有單點問題,single-point-of-failure)整個叢集系統将無法按照預期的方式運作。是以有必要将sentinel叢集,這樣有幾個好處:
- 即使有一些sentinel程序宕掉了,依然可以進行redis叢集的主備切換;
- 如果隻有一個sentinel程序,如果這個程序運作出錯,或者是網絡堵塞,那麼将無法實作redis叢集的主備切換(單點問題);
- 如果有多個sentinel,redis的用戶端可以随意地連接配接任意一個sentinel來獲得關于redis叢集中的資訊。
5.部署前要了解哨兵的基本知識
- 為了進行健壯的部署,您至少需要三個哨兵執行個體。
- 三個哨兵執行個體應該放置在客戶使用獨立方式确認故障的計算機或虛拟機中。例如不同的實體機或不同可用區域的虛拟機。
- Sentinel+Redis分布式系統不保證在失敗時保留已确認的寫操作,因為Redis使用異步複制。但是,有一些方法可以部署Sentinel,使視窗在特定時間内丢失寫操作,而還有其他不太安全的方法可以部署它。
- 你的用戶端要支援哨兵,流行的用戶端都支援哨兵,但不是全部。
- 如果您不經常在開發環境中進行測試,那麼沒有安全的HA設定,或者如果您可以在生産環境中進行測試,如果它們工作的話,就沒有更好的HA設定。你可能有一個錯誤的配置,這将變得明顯,隻有當它太晚(淩晨3點,當你的主人停止工作)。
- Sentinel、Docker或其他形式的網絡位址轉換或端口映射應謹慎混合使用:Docker執行端口重新映射,Docker執行端口重新映射,破壞Sentinel自動發現其他的哨兵程序和master的slave清單。
6.配置哨兵監控master(不使用docker)
1.建立并且配置sentinel.conf
port 26379
pidfile "/usr/local/redis/sentinel/redis-sentinel.pid"
dir "/usr/local/redis/sentinel"
daemonize yes
protected-mode no
logfile "/usr/local/redis/sentinel/redis-sentinel.log"
# 配置哨兵 Redis監控一個master叫做mymaster,它的位址在127.0.0.1,端口為6379,票數是2, 這裡需要舉例說明一下,比如redis叢集中有5個sentinel執行個體,其中master挂掉,如果這裡的票數是2,表示有2個sentinel認為master挂掉,才能被認為是正真的挂掉
sentinel monitor mymaster 127.0.0.1 6379 2
# 密碼,這裡需要改成自己的master節點redis密碼
sentinel auth-pass mymaster <password>
# master被sentinel認定為失效的間隔時間
sentinel down-after-milliseconds mymaster 30000
# 剩餘的slaves重新和新的master做同步的并行個數
sentinel parallel-syncs mymaster 1
# 主備切換的逾時時間,哨兵要去做故障轉移,這個時候哨兵也是一個程序,如果他沒有去執行,超過這個時間後,會由其他的哨兵來處理
sentinel failover-timeout mymaster 180000
2.啟動哨兵X3,在不同伺服器上啟動
redis-sentinel sentinel.conf
3.測試
1.master挂掉,看slave是否成為master
2.master挂掉,觀察slave狀态
結果
master挂了以後,由于哨兵監控,剩餘slave會進行選舉,選舉後其中一個成為master,當原來的master恢複後,他會成為slave。
7.配置哨兵監控master(使用docker)
為了示範友善,我隻是在一台伺服器上進行操作,實際業務中,redis主從和哨兵應分别部署在不同的伺服器上,這樣保證其健壯性。下面是示範圖,使用一主二從三哨兵。此處不介紹redis主從複制,預設一主二從已啟動,詳細請參照Redis的主從複制原理及docker環境下的實操
+----+ +----+ +----+
| R1 |----+----| M1 |----+----| R1 |
+----+ | +----+ | +----+
| |
+------+-------+------+-----+
| | |
| | |
+----+ +----+ +----+
| S1 | | S2 | | S3 |
+----+ +----+ +----+
1.建立并且配置sentinel.conf
# Base
port 26379
pidfile "/etc/redis/sentinel/redis-sentinel.pid"
dir "/etc/redis/sentinel"
protected-mode no
logfile "/etc/redis/sentinel/redis-sentinel.log"
# Core
# 配置哨兵
sentinel monitor mymaster 127.0.0.1 6379 2
# 密碼
sentinel auth-pass mymaster <password>
# master被sentinel認定為失效的間隔時間
sentinel down-after-milliseconds mymaster 30000
# 剩餘的slaves重新和新的master做同步的并行個數
sentinel parallel-syncs mymaster 1
# 主備切換的逾時時間,哨兵要去做故障轉移,這個時候哨兵也是一個程序,如果他沒有去執行,超過這個時間後,會由其他的哨兵來處理
sentinel failover-timeout mymaster 180000
注: 和剛剛的配置不同的是,當使用docker單獨給sentinel作為一個容器時,需要将daemonize no,或者直接删除該配置(daemonize yes用來指定redis是否用守護線程的方式啟動)
2.建立docker-compose.yml檔案
services:
redis-sentinel-1:
image: redis
container_name: redis-sentinel-1
restart: always
# 為了規避Docker中端口映射可能帶來的問題
# 這裡選擇使用host網絡
# network_mode: host
ports:
- 26379:26379
volumes:
- ./redis-sentinel.conf:/etc/redis/redis-sentinel.conf
- ./log/redis-sentinel-1.log:/etc/redis/sentinel/redis-sentinel.log
# 指定時區,保證容器内時間正确
environment:
TZ: "Asia/Shanghai"
sysctls:
net.core.somaxconn: '511'
command: ["redis-sentinel", "/etc/redis/redis-sentinel.conf"]
redis-sentinel-2:
image: redis
container_name: redis-sentinel-2
restart: always
ports:
- 26380:26379
volumes:
- ./redis-sentinel.conf:/etc/redis/redis-sentinel.conf
- ./log/redis-sentinel-2.log:/etc/redis/sentinel/redis-sentinel.log
environment:
TZ: "Asia/Shanghai"
sysctls:
net.core.somaxconn: '511'
command: ["redis-sentinel", "/etc/redis/redis-sentinel.conf"]
redis-sentinel-3:
image: redis
container_name: redis-sentinel-3
restart: always
ports:
- 26381:26379
volumes:
- ./redis-sentinel.conf:/etc/redis/redis-sentinel.conf
- ./log/redis-sentinel-3.log:/etc/redis/sentinel/redis-sentinel.log
environment:
TZ: "Asia/Shanghai"
sysctls:
net.core.somaxconn: '511'
command: ["redis-sentinel", "/etc/redis/redis-sentinel.conf"]
具體檔案目錄如下圖
3.啟動redis-sentinel
在/mydate/redis/sentinel目錄下執行指令 docker-compose up -d
4.檢視啟動狀态
(1)啟動後使用 docker ps -a
(2)docker exec -it redis-sentinel-1 /bin/bash 進行哨兵容器内部
#檢視mymaster下的master節點資訊
sentinel master mymaster
#檢視mymaster下的slaves 節點資訊
sentinel slaves mymaster
#檢視mymaster下的sentinel哨兵節點資訊
sentinel sentinels mymaster
(3)當redis的master節點挂掉後,檢視從節點情況
- 使用docker stop redis-6379命名停止redis的master節點容器運作
- 進入容器内部檢視redis資訊,發現redis-6380已經成為了master節點
- 重新啟動 docker restart redis-6379 進入容器内部檢視redis資訊,發現redis-6379已經成為了slave節點
5.原Master恢複後不同步問題
該過程可能會遇到一個問題,原來的master恢複成為slave後,他的同步狀态不ok,狀态為
master_link_status:down
,原因是因為我們在主從複制的時候,隻改了從節點的masterauth,一開始是不受影響的,但當master恢複成為slave後,由于他沒有設定
masterauth
,是以不能從新的master上同步資料,導緻我們在
info replication
時,同步狀态為
down
,是以隻需要修改redis.conf中的
masterauth
即可。主從的
masterauth
需保持一緻,進而無論那個節點成為master,都不會因為masterauth導緻同步狀态down掉。
一般master資料無法同步給slave的方案檢查如下:
- 網絡通信問題,要保證互相ping通,内網互通。
- 關閉防火牆,對應的端口開放。(虛拟機中建議永久關閉防火牆,雲伺服器的話需要保證内網互通)。
- 同意所有的密碼,通過逐台檢查機器以防某個節點被遺漏。
8.springboot內建redis哨兵
将單執行個體的配置替換為下面的配置即可
spring:
redis:
database: 1
password: 123456 ##密碼為master的密碼
sentinel:
master: mymaster ##配置檔案中的自定義主節點名稱
nodes: 47.94.93.93:26379,47.94.93.93:26380,47.94.93.93:26381