Redis Sentinel介紹
Redis Sentinel是Redis的官方高可用性解決方案
Redis Sentinel為Redis提供高可用性。實際上,這意味着使用Sentinel可以創建一個Redis部署,可以在沒有人為干預的情況下抵御某些類型的故障。
Redis Sentinel還提供其他附屬任務,如監控,通知,並充當客戶端的配置提供程序。
這是宏觀級別的Sentinel功能的完整列表(即大圖):
- 監控。Sentinel會不斷檢查主實例和從屬實例是否按預期工作。
- 通知。Sentinel可以通過API通知系統管理員,另一台計算機程序,其中一個受監控的Redis實例出現問題。
- 自動故障轉移。如果主服務器未按預期工作,Sentinel可以啟動故障轉移過程,其中從服務器升級為主服務器,其他其他服務器重新配置為使用新主服務器,並且使用Redis服務器的應用程序通知有關新服務器的地址。連接。
- 配置提供商。Sentinel充當客戶端服務發現的權限來源:客戶端連接到Sentinels,以便詢問負責給定服務的當前Redis主服務器的地址。如果發生故障轉移,Sentinels將報告新地址
Redis Sentinel搭建
本例在同一台機器上搭建,實際搭建,可以分三台機器進行搭建

| 服務類型 | 角色 | IP地址 | 端口 |
|---|---|---|---|
| Redis | master | 127.0.0.1 | 17007 |
| Redis | slave | 127.0.0.1 | 17008 |
| Redis | slave | 127.0.0.1 | 17009 |
| Sentinel | 127.0.0.1 | 17107 | |
| Sentinel | 127.0.0.1 | 17108 | |
| Sentinel | 127.0.0.1 | 17109 |
1、搭建3個節點的主從模式redis,參考:【Redis】Redis 主從模式搭建
目錄如下:

2、搭建Sentinel節點,17107節點配置文件如下:
1 # bind注釋掉,需要在外網訪問,將protected-model改為no 2 protected-mode no 3 4 # 端口 5 port 17107 6 7 # 后台運行 8 daemonize yes 9 10 # pid文件 11 pidfile sentinel_17107.pid 12 13 # 日志文件 14 logfile "/data/log/redis-sentinel-log/sentinel-17107-log/sentinel-17107.log" 15 16 # 目錄 17 dir /data/soft/redis-sentinel/sentinel-17107/ 18 19 # sentinel monitor <master-name> <ip> <redis-port> <quorum> 20 # 配置sentinel監控的master 21 # sentinel監控的master的名字叫做mymaster,地址為127.0.0.1:6379 22 # sentinel在集群式時,需要多個sentinel互相溝通來確認某個master是否真的死了; 23 # 數字2代表,當集群中有2個sentinel認為master死了時,才能真正認為該master已經不可用了。 24 sentinel monitor mymaster 127.0.0.1 17007 2 25 26 # sentinel auth-pass <master-name> <password> 27 # sentinel author-pass定義服務的密碼,mymaster是服務名稱,123456是Redis服務器密碼 28 sentinel auth-pass mymaster 123456 29 30 # sentinel down-after-milliseconds <master-name> <milliseconds> 31 # sentinel會向master發送心跳PING來確認master是否存活 32 # 如果master在“一定時間范圍”內不回應PONG或者是回復了一個錯誤消息 33 # 那么這個sentinel會主觀地認為這個master已經不可用了(SDOWN) 34 # 而這個down-after-milliseconds就是用來指定這個“一定時間范圍”的,單位是毫秒。 35 sentinel down-after-milliseconds mymaster 30000 36 37 # sentinel parallel-syncs <master-name> <numreplicas> 38 # 在發生failover主備切換時,這個選項指定了最多可以有多少個slave同時對新的master進行同步 39 # 這個數字越小,完成failover所需的時間就越長 40 # 但是如果這個數字越大,就意味着越多的slave因為replication而不可用。 41 # 可以通過將這個值設為 1 來保證每次只有一個slave處於不能處理命令請求的狀態。 42 sentinel parallel-syncs mymaster 1 43 44 # sentinel failover-timeout <master-name> <milliseconds> 45 # 實現主從切換,完成故障轉移的所需要的最大時間值。 46 # 若Sentinel進程在該配置值內未能完成故障轉移的操作,則認為本次故障轉移操作失敗。 47 sentinel failover-timeout mymaster 180000 48 49 # 指定Sentinel進程檢測到Master-Name所指定的“Master主服務器”的實例異常的時候,所要調用的報警腳本。 50 # sentinel notification-script mymaster <script-path> 51 52 # 安全 53 # 避免腳本重置,默認值yes 54 # 默認情況下,SENTINEL SET將無法在運行時更改notification-script和client-reconfig-script。 55 # 這避免了一個簡單的安全問題,客戶端可以將腳本設置為任何內容並觸發故障轉移以便執行程序。 56 sentinel deny-scripts-reconfig yes
3、啟動Redis Sentinel
注意啟動的順序。首先是redis主節點的Redis服務進程,然后啟動從機的服務進程,最后啟動3個哨兵的服務進程。
啟動Sentinel方式
方式1:redis-sentinel redis-sentinel.conf
方式2:redis-server sentinel.conf --sentinel
本例編輯了一個腳本(start-all.sh)進行啟動,內容如下:
1 #!/bin/bash 2 3 # 啟動 Redis-Server 4 echo "Star Redis-Server ..." 5 6 cd /data/soft/redis-sentinel 7 redis-5.0.5/src/redis-server redis-17007/redis-17007.conf 8 9 # sleep 1 睡眠1秒 10 # sleep 1s 睡眠1秒 11 # sleep 1m 睡眠1分 12 # sleep 1h 睡眠1小時 13 sleep 3 14 15 redis-5.0.5/src/redis-server redis-17008/redis-17008.conf 16 redis-5.0.5/src/redis-server redis-17009/redis-17009.conf 17 18 # 啟動 Redis-Sentinel 19 echo "Star Redis-Sentinel ..." 20 21 redis-5.0.5/src/redis-sentinel sentinel-17107/sentinel-17107.conf 22 redis-5.0.5/src/redis-sentinel sentinel-17108/sentinel-17108.conf 23 redis-5.0.5/src/redis-sentinel sentinel-17109/sentinel-17109.conf
關閉腳本(start-all.sh)
1 #!/bin/bash 2 3 # 停止 Redis-Server 4 echo "Shutdown Redis-Sentinel ..." 5 6 cd /data/soft/redis-sentinel 7 8 redis-5.0.5/src/redis-cli -h 127.0.0.1 -p 17107 shutdown 9 redis-5.0.5/src/redis-cli -h 127.0.0.1 -p 17108 shutdown 10 redis-5.0.5/src/redis-cli -h 127.0.0.1 -p 17109 shutdown 11 12 # 停止 Redis-Server 13 echo "Shutdown Redis-Server ..." 14 15 redis-5.0.5/src/redis-cli -h 127.0.0.1 -p 17007 -a 123456 shutdown 16 redis-5.0.5/src/redis-cli -h 127.0.0.1 -p 17008 -a 123456 shutdown 17 redis-5.0.5/src/redis-cli -h 127.0.0.1 -p 17009 -a 123456 shutdown
4、測試用客戶端連接redis,進行操作,使用命令:redis-5.0.5/src/redis-cli -h 127.0.0.1 -p 17007 -a 123456
Redis Sentinel Java連接
使用Jedis連接Redis,測試類如下:
1 package com.test.jedis; 2 3 import java.util.Arrays; 4 import java.util.HashSet; 5 import java.util.Set; 6 7 import org.junit.Test; 8 9 import redis.clients.jedis.Jedis; 10 import redis.clients.jedis.JedisPoolConfig; 11 import redis.clients.jedis.JedisSentinelPool; 12 13 public class TestSentinels { 14 15 @Test 16 public void testSentinel() { 17 JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); 18 jedisPoolConfig.setMaxTotal(10); 19 jedisPoolConfig.setMaxIdle(5); 20 jedisPoolConfig.setMinIdle(5); 21 // 哨兵信息 22 Set<String> sentinels = new HashSet<String>(Arrays.asList("127.0.0.1:17107", "127.0.0.1:17108","127.0.0.1:17109")); 23 // 創建連接池 24 JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels,"123456"); 25 // 獲取客戶端 26 Jedis jedis = pool.getResource(); 27 // 執行兩個命令 28 jedis.set("mykey", "myvalue"); 29 String value = jedis.get("mykey"); 30 System.out.println(value); 31 } 32 }
測試故障轉移
1、模擬發生故障,使用命令關閉主Redis節點17001,命令:redis-5.0.5/src/redis-cli -h 127.0.0.1 -p 17007 -a 123456 shutdown
2、查看日志Redis Sentinel(17107)節點日志,如下
2564:X 25 Aug 2019 16:18:42.215 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 2564:X 25 Aug 2019 16:18:42.215 # Redis version=5.0.5, bits=64, commit=00000000, modified=0, pid=2564, just started 2564:X 25 Aug 2019 16:18:42.215 # Configuration loaded 2571:X 25 Aug 2019 16:18:42.222 * Running mode=sentinel, port=17107. 2571:X 25 Aug 2019 16:18:42.234 # Sentinel ID is 4e78a59c5ac6f8aa23bd0a22bbb1741faa6d6ce5 2571:X 25 Aug 2019 16:18:42.235 # +monitor master mymaster 127.0.0.1 17007 quorum 2 2571:X 25 Aug 2019 16:18:42.240 * +slave slave 127.0.0.1:17008 127.0.0.1 17008 @ mymaster 127.0.0.1 17007 2571:X 25 Aug 2019 16:18:42.244 * +slave slave 127.0.0.1:17009 127.0.0.1 17009 @ mymaster 127.0.0.1 17007 2571:X 25 Aug 2019 16:18:44.282 * +sentinel sentinel 0c009020ab689e56f755e8756818c667f04baa45 127.0.0.1 17108 @ mymaster 127.0.0.1 17007 2571:X 25 Aug 2019 16:18:44.319 * +sentinel sentinel 7248affc9dd5089ef46b6943b89652a33f23f4cf 127.0.0.1 17109 @ mymaster 127.0.0.1 17007 2571:X 25 Aug 2019 16:19:42.017 # +sdown master mymaster 127.0.0.1 17007 2571:X 25 Aug 2019 16:19:42.043 # +new-epoch 1 2571:X 25 Aug 2019 16:19:42.048 # +vote-for-leader 0c009020ab689e56f755e8756818c667f04baa45 1 2571:X 25 Aug 2019 16:19:42.093 # +odown master mymaster 127.0.0.1 17007 #quorum 3/2 2571:X 25 Aug 2019 16:19:42.093 # Next failover delay: I will not start a failover before Sun Aug 25 16:25:42 2019 2571:X 25 Aug 2019 16:19:42.641 # +config-update-from sentinel 0c009020ab689e56f755e8756818c667f04baa45 127.0.0.1 17108 @ mymaster 127.0.0.1 17007 2571:X 25 Aug 2019 16:19:42.641 # +switch-master mymaster 127.0.0.1 17007 127.0.0.1 17008 2571:X 25 Aug 2019 16:19:42.641 * +slave slave 127.0.0.1:17009 127.0.0.1 17009 @ mymaster 127.0.0.1 17008 2571:X 25 Aug 2019 16:19:42.641 * +slave slave 127.0.0.1:17007 127.0.0.1 17007 @ mymaster 127.0.0.1 17008 2571:X 25 Aug 2019 16:20:12.693 # +sdown slave 127.0.0.1:17007 127.0.0.1 17007 @ mymaster 127.0.0.1 17008
從日志上可以看出
a、主觀下線(sdown)
當某個哨兵心跳檢測master超時后,則認定其sdown
+sdown master mymaster 127.0.0.1 17007
b、客觀下線(odown)
當認定sdown的哨兵數>=quorum時,則master下線事實最終成立,即odown
+odown master mymaster 172.31.175.142 6379 #quorum 2/2
c、選舉哨兵leader
各哨兵協商,選舉出一個leader,由其進行故障轉移操作
+vote-for-leader 0c009020ab689e56f755e8756818c667f04baa45 1
d、故障轉移
選擇一個slave作為新的master, 並將其他節點設置為新master的slave (剛才已下線的老master的配置文件也會被設置slaveof…)
+switch-master mymaster 127.0.0.1 17007 127.0.0.1 17008
當故障轉移成功后, redis是一主一從, 如下
127.0.0.1:17008> info Replication # Replication role:master connected_slaves:1 slave0:ip=127.0.0.1,port=17009,state=online,offset=261636,lag=0
3、故障恢復
模擬故障恢復,重啟redis-server的17007節點, 之后查看其redis主從信息, 發現老的master已經變成slave了,如下
127.0.0.1:17008> info Replication # Replication role:master connected_slaves:2 slave0:ip=127.0.0.1,port=17009,state=online,offset=303086,lag=0 slave1:ip=127.0.0.1,port=17007,state=online,offset=303086,lag=0
