目录
1、配置文件
(1) Redis主节点配置文件
(2) Redis从节点配置文件
(3) Sentinel(哨兵)配置文件
2、启动Redis服务和哨兵
(1) 启动3个Redis服务
(2) 启动3个哨兵
3、客户端连接
(1) 客户端哨兵读写分离配置
(2) 故障转移测试用例
(3) 停掉master节点模拟宕机
1、配置文件
Redis版本为6.0.4,准备了6个配置文件,3个Redis服务配置文件,3个哨兵配置文件,部署方式为一主二从三哨兵。
(1) Redis主节点配置文件
redis-6380.conf
# 配置文件进行了精简,完整配置可自行和官方提供的完整conf文件进行对照。端口号自行对应修改 #后台启动的意思 daemonize yes #端口号(如果同一台服务器上启动,注意要修改为不同的端口) port 6380 # IP绑定,redis不建议对公网开放,直接绑定0.0.0.0没毛病 bind 172.17.0.13 127.0.0.1 # 日志文件 logfile "/redis/logs/redis-6380.log" # 工作目录,用来存储持久化文件 dir "/redis/workingDir"
(2) Redis从节点配置文件
redis-6381.conf、redis-6382.conf
# 配置文件进行了精简,完整配置可自行和官方提供的完整conf文件进行对照。端口号自行对应修改 #后台启动的意思 daemonize yes #端口号(如果同一台服务器上启动,注意要修改为不同的端口) port 6381 # IP绑定,redis不建议对公网开放,直接绑定0.0.0.0没毛病 bind 172.17.0.13 127.0.0.1 # 日志文件 logfile "/redis/logs/redis-6381.log" # 工作目录,用来存储持久化文件 dir "/redis/workingDir" # 复制选项 replicaof 122.51.151.130 6380
如果客户端是通过公网ip连接,replicaof 122.51.151.130 6380从节点复制配置要特别注意,改成公网ip而不是私网ip,由于从节点是通过公网ip和主节点通信,因此相关端口在安全组中一定要放开。
下面哨兵配置监控的也是公网ip,复制项如果配的私网ip,会导致哨兵切主时失败。这里比较奇怪,哨兵选出了晋升的从节点,但从节点角色还是role。如果复制项的主节点ip和哨兵监控的主节点ip都为公网或私网ip,则不会出现这种情况。
(3) Sentinel(哨兵)配置文件
#配置文件:Sentinel.conf,在sentinel运行期间是会被动态修改的 # sentinel如果重启时,根据这个配置来恢复其之前所监控的redis集群的状态 # 绑定IP bind 172.17.0.13 127.0.0.1 # 后台运行 daemonize yes # 默认yes,没指定密码或者指定IP的情况下,外网无法访问 protected-mode no # 哨兵的端口,客户端通过这个端口来发现redis port 26381 # 哨兵自己的IP,手动设定也可自动发现,用于与其他哨兵通信 # sentinel announce-ip # 工作目录 dir "/redis/workingDir" # 日志 logfile "/redis/logs/sentinel-26381.log" # sentinel监控的master的名字叫做mymaster,初始地址为 127.0.0.1 6380,2代表两个及以上哨兵认定为死亡,才认为是真的死亡 sentinel monitor mymaster 122.51.151.130 6380 2 # 发送心跳PING来确认master是否存活 # 如果master在“一定时间范围”内不回应PONG 或者是回复了一个错误消息,那么这个sentinel会主观地(单方面地)认为这个master已经不可用了 sentinel down-after-milliseconds mymaster 1000 # 如果在该时间(ms)内未能完成failover操作,则认为该failover失败 sentinel failover-timeout mymaster 3000 # 指定了在执行故障转移时,最多可以有多少个从Redis实例在同步新的主实例,在从Redis实例较多的情况下这个数字越小,同步的时间越长,完成故障转移所需的时间就越长 sentinel parallel-syncs mymaster 1
2、启动Redis服务和哨兵
(1) 启动3个Redis服务
redis-server redis-6380.conf redis-server redis-6381.conf redis-server redis-6382.conf
启动完成后,查看主从复制信息:
[universe@VM_0_13_centos sentinel]$ redis-cli -p 6380 127.0.0.1:6380> info replication # Replication role:master connected_slaves:2 slave0:ip=122.51.151.130,port=6381,state=online,offset=14821,lag=1 slave1:ip=122.51.151.130,port=6382,state=online,offset=14821,lag=1 master_replid:ced7289a3295ce73e9b538b0d69a7ce1e7bfdb54 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:15241 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:15241
现在主从复制是okay的,当前6380为主节点,6381和6382为从节点。
(2) 启动3个哨兵
redis-sentinel sentinel-26380.conf redis-sentinel sentinel-26381.conf redis-sentinel sentinel-26382.conf
[universe@VM_0_13_centos sentinel]$ redis-cli -p 26381 127.0.0.1:26381> 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=122.51.151.130:6380,slaves=2,sentinels=3
3、客户端连接
(1) 客户端哨兵读写分离配置
@Configuration public class RedisSentinelConfig { @Bean public RedisConnectionFactory redisConnectionFactory() { LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder() .readFrom(ReadFrom.REPLICA_PREFERRED) .build(); // 指定监控的master以及哨兵地址、端口 RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration() .master("mymaster") .sentinel("122.51.151.130", 26380) .sentinel("122.51.151.130", 26381) .sentinel("122.51.151.130", 26382); return new LettuceConnectionFactory(sentinelConfig, clientConfig); } }
(2) 故障转移测试用例
@RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) public class RedisSentinelTest { @Autowired private StringRedisTemplate stringRedisTemplate; /** * 期间关掉master,哨兵会进行自动故障切换,客户端重连到新的master * @throws InterruptedException */ @Test public void automaticFailoverTest() throws InterruptedException { int count = 0; while (true) { try { stringRedisTemplate.opsForValue().set("count", String.valueOf(++count)); } catch (RedisSystemException e) { System.out.println("可能发生切主,命令被取消,重连....."); stringRedisTemplate.opsForValue().set("count", String.valueOf(++count)); } System.out.println("修改count的值,当前值为:" + count); Thread.sleep(2000); System.out.println("获取count的值,当前值为:" + stringRedisTemplate.opsForValue().get("count")); } } }
(3) 停掉master节点模拟宕机
把当前主节点6380干掉后,哨兵会进行切主,我们可以再次查看哨兵状态信息:
[universe@VM_0_13_centos sentinel]$ redis-cli -p 26380 127.0.0.1:26380> 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=122.51.151.130:6382,slaves=2,sentinels=3
主节点6380挂掉后程序还是是正常运行的,程序运行结果如下:
修改count的值,当前值为:1 获取count的值,当前值为:1 修改count的值,当前值为:2 获取count的值,当前值为:2 修改count的值,当前值为:3 获取count的值,当前值为:3 修改count的值,当前值为:4 获取count的值,当前值为:4 修改count的值,当前值为:5 获取count的值,当前值为:5 修改count的值,当前值为:6 获取count的值,当前值为:6 修改count的值,当前值为:7 获取count的值,当前值为:7 修改count的值,当前值为:8 2020-09-02 16:14:07.785 INFO 13140 --- [xecutorLoop-1-2] i.l.core.protocol.ConnectionWatchdog : Reconnecting, last destination was /122.51.151.130:6380 获取count的值,当前值为:8 2020-09-02 16:14:08.885 WARN 13140 --- [ioEventLoop-6-3] i.l.core.protocol.ConnectionWatchdog : Cannot reconnect to [122.51.151.130:6380]: Connection refused: no further information: /122.51.151.130:6380 2020-09-02 16:14:09.084 INFO 13140 --- [xecutorLoop-1-3] i.l.core.protocol.ConnectionWatchdog : Reconnecting, last destination was /122.51.151.130:6382 2020-09-02 16:14:09.118 INFO 13140 --- [ioEventLoop-6-1] i.l.core.protocol.ReconnectionHandler : Reconnected to 122.51.151.130:6382 2020-09-02 16:14:09.985 INFO 13140 --- [xecutorLoop-1-4] i.l.core.protocol.ConnectionWatchdog : Reconnecting, last destination was /122.51.151.130:6381 2020-09-02 16:14:10.016 INFO 13140 --- [ioEventLoop-6-2] i.l.core.protocol.ReconnectionHandler : Reconnected to 122.51.151.130:6381 2020-09-02 16:14:13.684 INFO 13140 --- [xecutorLoop-1-4] i.l.core.protocol.ConnectionWatchdog : Reconnecting, last destination was 122.51.151.130:6380 2020-09-02 16:14:14.086 WARN 13140 --- [ioEventLoop-6-4] i.l.core.protocol.ConnectionWatchdog : Cannot reconnect to [122.51.151.130:6380]: java.util.concurrent.CancellationException 可能发生切主,命令被取消,重连..... 修改count的值,当前值为:10 获取count的值,当前值为:10 修改count的值,当前值为:11 获取count的值,当前值为:11 修改count的值,当前值为:12