【Redis】Redis Sentinel 哨兵模式搭建

时间:2023-12-09 20:17:07

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搭建

  本例在同一台机器上搭建,实际搭建,可以分三台机器进行搭建

  【Redis】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 主从模式搭建

    目录如下:

    【Redis】Redis Sentinel 哨兵模式搭建

  2、搭建Sentinel节点,17107节点配置文件如下:

 # bind注释掉,需要在外网访问,将protected-model改为no
protected-mode no # 端口
port 17107 # 后台运行
daemonize yes # pid文件
pidfile sentinel_17107.pid # 日志文件
logfile "/data/log/redis-sentinel-log/sentinel-17107-log/sentinel-17107.log" # 目录
dir /data/soft/redis-sentinel/sentinel-17107/ # sentinel monitor <master-name> <ip> <redis-port> <quorum>
# 配置sentinel监控的master
# sentinel监控的master的名字叫做mymaster,地址为127.0.0.1:6379
# sentinel在集群式时,需要多个sentinel互相沟通来确认某个master是否真的死了;
# 数字2代表,当集群中有2个sentinel认为master死了时,才能真正认为该master已经不可用了。
sentinel monitor mymaster 127.0.0.1 17007 2 # sentinel auth-pass <master-name> <password>
# sentinel author-pass定义服务的密码,mymaster是服务名称,123456是Redis服务器密码
sentinel auth-pass mymaster 123456 # sentinel down-after-milliseconds <master-name> <milliseconds>
# sentinel会向master发送心跳PING来确认master是否存活
# 如果master在“一定时间范围”内不回应PONG或者是回复了一个错误消息
# 那么这个sentinel会主观地认为这个master已经不可用了(SDOWN)
# 而这个down-after-milliseconds就是用来指定这个“一定时间范围”的,单位是毫秒。
sentinel down-after-milliseconds mymaster 30000 # sentinel parallel-syncs <master-name> <numreplicas>
# 在发生failover主备切换时,这个选项指定了最多可以有多少个slave同时对新的master进行同步
# 这个数字越小,完成failover所需的时间就越长
# 但是如果这个数字越大,就意味着越多的slave因为replication而不可用。
# 可以通过将这个值设为 1 来保证每次只有一个slave处于不能处理命令请求的状态。
sentinel parallel-syncs mymaster 1 # sentinel failover-timeout <master-name> <milliseconds>
# 实现主从切换,完成故障转移的所需要的最大时间值。
# 若Sentinel进程在该配置值内未能完成故障转移的操作,则认为本次故障转移操作失败。
sentinel failover-timeout mymaster 180000 # 指定Sentinel进程检测到Master-Name所指定的“Master主服务器”的实例异常的时候,所要调用的报警脚本。
# sentinel notification-script mymaster <script-path> # 安全
# 避免脚本重置,默认值yes
# 默认情况下,SENTINEL SET将无法在运行时更改notification-script和client-reconfig-script。
# 这避免了一个简单的安全问题,客户端可以将脚本设置为任何内容并触发故障转移以便执行程序。
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)进行启动,内容如下:

 #!/bin/bash

 # 启动 Redis-Server
echo "Star Redis-Server ..." cd /data/soft/redis-sentinel
redis-5.0.5/src/redis-server redis-17007/redis-17007.conf # sleep 1 睡眠1秒
# sleep 1s 睡眠1秒
# sleep 1m 睡眠1分
# sleep 1h 睡眠1小时
sleep 3 redis-5.0.5/src/redis-server redis-17008/redis-17008.conf
redis-5.0.5/src/redis-server redis-17009/redis-17009.conf # 启动 Redis-Sentinel
echo "Star Redis-Sentinel ..." redis-5.0.5/src/redis-sentinel sentinel-17107/sentinel-17107.conf
redis-5.0.5/src/redis-sentinel sentinel-17108/sentinel-17108.conf
redis-5.0.5/src/redis-sentinel sentinel-17109/sentinel-17109.conf

    关闭脚本(start-all.sh)

 #!/bin/bash

 # 停止 Redis-Server
echo "Shutdown Redis-Sentinel ..." cd /data/soft/redis-sentinel redis-5.0.5/src/redis-cli -h 127.0.0.1 -p 17107 shutdown
redis-5.0.5/src/redis-cli -h 127.0.0.1 -p 17108 shutdown
redis-5.0.5/src/redis-cli -h 127.0.0.1 -p 17109 shutdown # 停止 Redis-Server
echo "Shutdown Redis-Server ..." redis-5.0.5/src/redis-cli -h 127.0.0.1 -p 17007 -a 123456 shutdown
redis-5.0.5/src/redis-cli -h 127.0.0.1 -p 17008 -a 123456 shutdown
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,测试类如下:

 package com.test.jedis;

 import java.util.Arrays;
import java.util.HashSet;
import java.util.Set; import org.junit.Test; import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool; public class TestSentinels { @Test
public void testSentinel() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(10);
jedisPoolConfig.setMaxIdle(5);
jedisPoolConfig.setMinIdle(5);
// 哨兵信息
Set<String> sentinels = new HashSet<String>(Arrays.asList("127.0.0.1:17107", "127.0.0.1:17108","127.0.0.1:17109"));
// 创建连接池
JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels,"123456");
// 获取客户端
Jedis jedis = pool.getResource();
// 执行两个命令
jedis.set("mykey", "myvalue");
String value = jedis.get("mykey");
System.out.println(value);
}
}

测试故障转移

  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