Linux学习-Redis哨兵

Posted 丢爸

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux学习-Redis哨兵相关的知识,希望对你有一定的参考价值。

Redis哨兵

Redis提供了哨兵(Sentinel)机制来实现主从集群的自动故障恢复
哨兵的作用:
1.监控:Sentinel会不断检查master和slave是否按预期工作
2.自动故障恢复:如果master故障,Sentinel会将一个slave提升为master,当故障实例恢复后也以新的master为主
3.通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis客户端


服务器状态监控
Sentinel基于心跳机制监控服务状态,每隔一秒向集群的每个实例发送ping命令
1.主观下线:如果某Sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线
2.客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线,quorum值超过Sentinel实例数量的一半

如何选举新的master?
1.首先判断slave节点与master节点断开时间长短,如果超过指定值(down-after-milliseconds*10)则会排除该slave节点
2.然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举
3.如果slave-priority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高
4最后是判断slave节点的运行id大小,越小优先级越高

如何进行故障转移?
1.Sentinel给备选的slave1节点发送slaveof no one命令,让该节点成为新master
2.Sentinel给所有其它slave发送slaveof 192.168.115.129 7002命令,让这些slave成为新master的从节点,开始从新master上同步数据
3.Sentinel将故障节点标记为slave,当故障节点恢复后自动成为新的master的slave节点
搭建哨兵
#1.在/opt下创建三个目录s1,s2,s3
[root@redis ~]# cd /opt
[root@redis opt]# ls
7001  7002  7003
[root@redis opt]# mkdir s1..3
[root@redis opt]# ls
7001  7002  7003  s1  s2  s3
#2.创建配置文件
[root@redis opt]# vim s1/sentinel.conf
#当前sentinel实例的端口
port 27001
sentinel announce-ip 192.168.115.129
`指定主节点信息,
  mymaster:主节点名称,自定义,任意写
  192.168.115.129 7001:主节点的IP和端口
  2:选举master时的quorum值
`
sentinel monitor mymaster 192.168.115.129 7001 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
dir "/opt/s1"
[root@redis opt]# echo s2 s3 | xargs -t -n 1 cp s1/sentinel.conf 
cp s1/sentinel.conf s2 
cp s1/sentinel.conf s3 
[root@redis opt]# sed -i -e 's/27001/27002/g' -e 's/s1/s2/g' s2/sentinel.conf 
[root@redis opt]# cat s2/sentinel.conf
port 27002
sentinel announce-ip 192.168.115.129
sentinel monitor mymaster 192.168.115.129 7001 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
dir "/opt/s1"
[root@redis opt]# sed -i -e 's/27001/27003/g' -e 's/s1/s3/g' s3/sentinel.conf 
使用哨兵
#在服务器上启动所有哨兵和redis
[root@redis opt]# redis-server 7001/redis.conf
[root@redis opt]# redis-server 7002/redis.conf
[root@redis opt]# redis-server 7003/redis.conf
[root@redis opt]# redis-sentinel s1/sentinel.conf
[root@redis opt]# redis-sentinel s2/sentinel.conf
[root@redis opt]# redis-sentinel s3/sentinel.conf
#通过spring-data-redis中redisTemplate使用哨兵
#在项目配置文件中添加sentinel配置信息application.yml
spring:
  redis:
    sentinel:
      master: mymaster
      nodes:
        - 192.168.115.129:27001
        - 192.168.115.129:27002
        - 192.168.115.129:27003
#配置主从读写分离
@Bean
    public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer() 
        return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
    
#ReadFrom配置读取策略,是一个枚举
1.MASTER:从主节点读取
2.MASTER_PREFERRED:优先从master节点读取,master不可用,才读取replica
3.REPLICA:从slave(replica)节点读取
4.REPLICA_PREFERRED;优先从slave(replica)节点读取,所有的slave都不可用时从master读取
#查看idea输出日志
1.设置键值
11-10 09:20:45:261 DEBUG 7512 --- [nio-8080-exec-9] io.lettuce.core.RedisChannelHandler      : dispatching command AsyncCommand [type=SET, output=StatusOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command]
11-10 09:20:45:261 DEBUG 7512 --- [nio-8080-exec-9] i.l.c.m.MasterSlaveConnectionProvider    : getConnectionAsync(WRITE)
11-10 09:20:45:261 DEBUG 7512 --- [nio-8080-exec-9] io.lettuce.core.RedisChannelHandler      : dispatching command AsyncCommand [type=SET, output=StatusOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command]
11-10 09:20:45:261 DEBUG 7512 --- [nio-8080-exec-9] i.lettuce.core.protocol.DefaultEndpoint  : [channel=0xa8219472, /192.168.115.1:61220 -> /192.168.115.129:7001, epid=0xd] write() writeAndFlush command AsyncCommand [type=SET, output=StatusOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command]
11-10 09:20:45:261 DEBUG 7512 --- [nio-8080-exec-9] i.lettuce.core.protocol.DefaultEndpoint  : [channel=0xa8219472, /192.168.115.1:61220 -> /192.168.115.129:7001, epid=0xd] write() done
11-10 09:20:45:261 DEBUG 7512 --- [ioEventLoop-4-3] io.lettuce.core.protocol.CommandHandler  : [channel=0xa8219472, /192.168.115.1:61220 -> /192.168.115.129:7001, chid=0x33] write(ctx, AsyncCommand [type=SET, output=StatusOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command], promise)
11-10 09:20:45:263 DEBUG 7512 --- [ioEventLoop-4-3] io.lettuce.core.protocol.CommandEncoder  : [channel=0xa8219472, /192.168.115.1:61220 -> /192.168.115.129:7001] writing command AsyncCommand [type=SET, output=StatusOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command]
11-10 09:20:45:265 DEBUG 7512 --- [ioEventLoop-4-3] io.lettuce.core.protocol.CommandHandler  : [channel=0xa8219472, /192.168.115.1:61220 -> /192.168.115.129:7001, chid=0x33] Received: 5 bytes, 1 commands in the stack
11-10 09:20:45:265 DEBUG 7512 --- [ioEventLoop-4-3] io.lettuce.core.protocol.CommandHandler  : [channel=0xa8219472, /192.168.115.1:61220 -> /192.168.115.129:7001, chid=0x33] Stack contains: 1 commands
11-10 09:20:45:265 DEBUG 7512 --- [ioEventLoop-4-3] i.l.core.protocol.RedisStateMachine      : Decode AsyncCommand [type=SET, output=StatusOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command]
11-10 09:20:45:265 DEBUG 7512 --- [ioEventLoop-4-3] i.l.core.protocol.RedisStateMachine      : Decoded AsyncCommand [type=SET, output=StatusOutput [output=OK, error='null'], commandType=io.lettuce.core.protocol.Command], empty stack: true
2.查看键值
11-10 09:22:33:885 DEBUG 7512 --- [nio-8080-exec-2] io.lettuce.core.RedisChannelHandler      : dispatching command AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command]
11-10 09:22:33:885 DEBUG 7512 --- [nio-8080-exec-2] i.l.c.m.MasterSlaveConnectionProvider    : getConnectionAsync(READ)
11-10 09:22:33:888 DEBUG 7512 --- [nio-8080-exec-2] io.lettuce.core.RedisClient              : Trying to get a Redis connection for: RedisURI [host='192.168.115.129', port=7003]
11-10 09:22:33:888 DEBUG 7512 --- [nio-8080-exec-2] io.lettuce.core.RedisClient              : Resolved SocketAddress 192.168.115.129/<unresolved>:7003 using RedisURI [host='192.168.115.129', port=7003]
11-10 09:22:33:888 DEBUG 7512 --- [nio-8080-exec-2] io.lettuce.core.RedisClient              : Connecting to Redis at 192.168.115.129/<unresolved>:7003
11-10 09:22:33:890 DEBUG 7512 --- [nio-8080-exec-2] io.lettuce.core.RedisClient              : Trying to get a Redis connection for: RedisURI [host='192.168.115.129', port=7002]
11-10 09:22:33:892 DEBUG 7512 --- [nio-8080-exec-2] io.lettuce.core.RedisClient              : Resolved SocketAddress 192.168.115.129/<unresolved>:7002 using RedisURI [host='192.168.115.129', port=7002]
11-10 09:22:33:892 DEBUG 7512 --- [nio-8080-exec-2] io.lettuce.core.RedisClient              : Connecting to Redis at 192.168.115.129/<unresolved>:7002
11-10 09:22:33:892 DEBUG 7512 --- [ioEventLoop-4-5] io.lettuce.core.protocol.CommandHandler  : [channel=0x8ea4709a, [id: 0x803d93f4] (inactive), chid=0x3d] channelRegistered()
11-10 09:22:33:894 DEBUG 7512 --- [ioEventLoop-4-6] io.lettuce.core.protocol.CommandHandler  : [channel=0x34cd4021, [id: 0x85a1cb96] (inactive), chid=0x3e] channelRegistered()
11-10 09:22:33:898 DEBUG 7512 --- [ioEventLoop-4-5] io.lettuce.core.protocol.CommandHandler  : [channel=0x8ea4709a, /192.168.115.1:64611 -> /192.168.115.129:7003, chid=0x3d] channelActive()
11-10 09:22:33:898 DEBUG 7512 --- [ioEventLoop-4-6] io.lettuce.core.protocol.CommandHandler  : [channel=0x34cd4021, /192.168.115.1:64612 -> /192.168.115.129:7002, chid=0x3e] channelActive()
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-6] i.lettuce.core.protocol.DefaultEndpoint  : [channel=0x34cd4021, /192.168.115.1:64612 -> /192.168.115.129:7002, epid=0x1f] activateEndpointAndExecuteBufferedCommands 0 command(s) buffered
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-5] i.lettuce.core.protocol.DefaultEndpoint  : [channel=0x8ea4709a, /192.168.115.1:64611 -> /192.168.115.129:7003, epid=0x1e] activateEndpointAndExecuteBufferedCommands 0 command(s) buffered
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-6] i.lettuce.core.protocol.DefaultEndpoint  : [channel=0x34cd4021, /192.168.115.1:64612 -> /192.168.115.129:7002, epid=0x1f] activating endpoint
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-6] i.lettuce.core.protocol.DefaultEndpoint  : [channel=0x34cd4021, /192.168.115.1:64612 -> /192.168.115.129:7002, epid=0x1f] flushCommands()
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-5] i.lettuce.core.protocol.DefaultEndpoint  : [channel=0x8ea4709a, /192.168.115.1:64611 -> /192.168.115.129:7003, epid=0x1e] activating endpoint
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-6] i.lettuce.core.protocol.DefaultEndpoint  : [channel=0x34cd4021, /192.168.115.1:64612 -> /192.168.115.129:7002, epid=0x1f] flushCommands() Flushing 0 commands
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-5] i.lettuce.core.protocol.DefaultEndpoint  : [channel=0x8ea4709a, /192.168.115.1:64611 -> /192.168.115.129:7003, epid=0x1e] flushCommands()
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-5] i.lettuce.core.protocol.DefaultEndpoint  : [channel=0x8ea4709a, /192.168.115.1:64611 -> /192.168.115.129:7003, epid=0x1e] flushCommands() Flushing 0 commands
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-6] i.l.core.protocol.ConnectionWatchdog     : [channel=0x34cd4021, /192.168.115.1:64612 -> /192.168.115.129:7002, last known addr=/192.168.115.129:7002] channelActive()
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-6] io.lettuce.core.protocol.CommandHandler  : [channel=0x34cd4021, /192.168.115.1:64612 -> /192.168.115.129:7002, chid=0x3e] channelActive() done
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-5] i.l.core.protocol.ConnectionWatchdog     : [channel=0x8ea4709a, /192.168.115.1:64611 -> /192.168.115.129:7003, last known addr=/192.168.115.129:7003] channelActive()
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-5] io.lettuce.core.protocol.CommandHandler  : [channel=0x8ea4709a, /192.168.115.1:64611 -> /192.168.115.129:7003, chid=0x3d] channelActive() done
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-6] io.lettuce.core.RedisClient              : Connecting to Redis at 192.168.115.129/<unresolved>:7002: Success
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-5] io.lettuce.core.RedisClient              : Connecting to Redis at 192.168.115.129/<unresolved>:7003: Success
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-6] i.l.core.protocol.ConnectionWatchdog     : [channel=0x34cd4021, /192.168.115.1:64612 -> /192.168.115.129:7002, last known addr=/192.168.115.129:7002] userEventTriggered(ctx, io.lettuce.core.ConnectionEvents$Activated@63b394dd)
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-5] io.lettuce.core.RedisChannelHandler      : dispatching command AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command]
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-5] i.lettuce.core.protocol.DefaultEndpoint  : [channel=0x8ea4709a, /192.168.115.1:64611 -> /192.168.115.129:7003, epid=0x1e] write() writeAndFlush command AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command]
11-10 09:22:33:900 DEBUG 7512 --- [ioEventLoop-4-5] io.lettuce.core.protocol.CommandHandler  : [channel=0x8ea4709a, /192.168.115.1:64611 -> /192.168.115.129:7003, chid=0x3d] write(ctx, AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command], promise)
11-10 09:22:33:902 DEBUG 7512 --- [ioEventLoop-4-5] io.lettuce.core.protocol.CommandEncoder  : [channel=0x8ea4709a, /192.168.115.1:64611 -> /192.168.115.129:7003] writing command AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command]
11-10 09:22:33:902 DEBUG 7512 --- [ioEventLoop-4-5] i.lettuce.core.protocol.DefaultEndpoint  : [channel=0x8ea4709a, /192.168.115.1:64611 -> /192.168.115.129:7003, epid=0x1e] write() done
11-10 09:22:33:903 DEBUG 7512 --- [ioEventLoop-4-5] i.l.core.protocol.ConnectionWatchdog     : [channel=0x8ea4709a, /192.168.115.1:64611 -> /192.168.115.129:7003, last known addr=/192.168.115.129:7003] userEventTriggered(ctx, io.lettuce.core.ConnectionEvents$Activated@76626038)
11-10 09:22:33:903 DEBUG 7512 --- [ioEventLoop-4-5] io.lettuce.core.protocol.CommandHandler  : [channel=0x8ea4709a, /192.168.115.1:64611 -> /192.168.115.129:7003, chid=0x3d] Received: 10 bytes, 1 commands in the stack
11-10 09:22:33:904 DEBUG 7512 --- [ioEventLoop-4-5] io.lettuce.core.protocol.CommandHandler  : [channel=0x8ea4709a, /192.168.115.1:64611 -> /192.168.115.129:7003, chid=0x3d] Stack contains: 1 commands
11-10 09:22:33:904 DEBUG 7512 --- [ioEventLoop-4-5] i.l.core.protocol.RedisStateMachine      : Decode AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command]
11-10 09:22:33:904 DEBUG 7512 --- [ioEventLoop-4-5] i.l.core.protocol.RedisStateMachine      : Decoded AsyncCommand [type=GET, output=ValueOutput [output=[B@43a98926, error='null'], commandType=io.lettuce.core.protocol.Command], empty stack: true
3.master宕机后,Sentinel会通过相应的规则 将另一台redis升级为master
EBUG 7512 --- [ioEventLoop-4-8] i.l.c.m.MasterSlaveConnectionProvider    : closeStaleConnections() count after expiring: 2
11-10 09:25:31:075 DEBUG 7512 --- [ioEventLoop-4-8] io.lettuce.core.protocol.CommandHandler  : [channel=0x961224db, /192.168.115.1:64679 -> /192.168.115.129:7003, chid=0x48] channelInactive()
11-10 09:25:31:075 DEBUG 7512 --- [ioEventLoop-4-5] io.lettuce.core.protocol.CommandHandler  : [channel=0x7c86c2e2, [id: 0x8447a484] (inactive), chid=0x45] channelUnregistered()
11-10 09:25:31:076 DEBUG 7512 --- [ioEventLoop-4-8] i.lettuce.core.protocol.DefaultEndpoint  : [channel=0x961224db, /192.168.115.1:64679 -> /192.168.115.129:7003, epid=0x22] deactivating endpoint handler
11-10 09:25:31:076 DEBUG 7512 --- [ioEventLoop-4-8] io.lettuce.core.protocol.CommandHandler  : [channel=0x961224db, /192.168.115.1:64679 -> /192.168.115.129:7003, chid=0x48] channelInactive() done
11-10 09:25:31:076 DEBUG 7512 --- [ioEventLoop-4-8] i.l.core.protocol.ConnectionWatchdog     : [channel=0x961224db, /192.168.115.1:64679 -> /192.168.115.129:7003, last known addr=/192.168.115.129:7003] channelInactive()
11-10 09:25:31:076 DEBUG 7512 --- [ioEventLoop-4-8] i.l.core.protocol.ConnectionWatchdog     : [channel=0x961224db, /192.168.115.1:64679 -> /192.168.115.129:7003, last known addr=/192.168.115.129:7003] Reconnect scheduling disabled
11-10 09:25:31:076 DEBUG 7512 --- [ioEventLoop-4-8] io.lettuce.core.protocol.CommandHandler  : [channel=0x961224db, /192.168.115.1:64679 -> /192.168.115.129:7003, chid=0x48] channelUnregistered()
11-10 09:25:32:124 DEBUG 7512 --- [ioEventLoop-4-2] io.lettuce.core.protocol.CommandHandler  : [channel=0x4585aa47, /192.168.115.1:59804 -> /192.168.115.129:27003, chid=0xa] Received: 123 bytes, 0 commands in the stack
11-10 09:25:32:124 DEBUG 7512 --- [ioEventLoop-4-2] i.l.core.protocol.RedisStateMachine      : Decode null
11-10 09:25:32:124 DEBUG 7512 --- [ioEventLoop-4-2] i.l.core.protocol.RedisStateMachine      : Decoded null, empty stack: true
11-10 09:25:32:126 DEBUG 7512 --- [ioEventLoop-4-2] i.l.c.m.SentinelTopologyRefresh          : Received topology changed signal from Redis Sentinel (+sdown), scheduling topology update
11-10 09:25:32:138 DEBUG 7512 --- [ioEventLoop-4-8] io.lettuce.core.protocol.CommandHandler  : [channel=0x9086940e, /192.168.115.1:59805 -> /192.168.115.129:27001, chid=0x8] Received: 123 bytes, 0 commands in the stack
11-10 09:25:32:138 DEBUG 7512 --- [ioEventLoop-4-8] i.l.core.protocol.RedisStateMachine      : Decode null
11-10 09:25:32:138 DEBUG 7512 --- [ioEventLoop-4-8] i.l.core.protocol.RedisStateMachine      : Decoded null, empty stack: true
11-10 09:25:33:152 DEBUG 7512 --- [ioEventLoop-4-1] io.lettuce.core.protocol.CommandHandler  : [channel=0x35b4d718, /192.168.115.1:59803 -> /192.168.115.129:27002, chid=0x9] Received: 123 bytes, 0 commands in the stack
11-10 09:25:33:154 DEBUG 7512 --- [ioEventLoop-4-1] i.l.core.protocol.RedisStateMachine      : Decode null
11-10 09:25:33:154 DEBUG 7512 --- [ioEventLoop-4-1] i.l.core.protocol.RedisStateMachine      : Decoded null, empty stack: true
11-10 09:25:37:130 DEBUG 7512 --- [xecutorLoop-1-1] i.l.core.masterslave.SentinelConnector   : Refreshing topology
11-10 09:25:37:130 DEBUG 7512 --- [xecutorLoop-1-1] i.l.c.m.SentinelTopologyProvider         : lookup topology for masterId mymaster
11-10 09:25:37:130 DEBUG 7512 --- [xecutorLoop-1-1] io.lettuce.core.RedisClient              : Trying to get a Redis Sentinel connection for one of: [RedisURI [host='192.168.115.129', port=27001], RedisURI [host='192.168.115.129', port=27002], RedisURI [host='192.168.115.129', port=27003]]
11-10 09:25:37:130 DEBUG 7512 --- [xecutorLoop-1-1] io.lettuce.core.RedisClient              : Connecting to Redis Sentinel, address: RedisURI [host='192.168.115.129', port=27001]
11-10 09:25:37:130 DEBUG 7512 --- [xecutorLoop-1-1] io.lettuce.core.RedisClient              : Resolved SocketAddress 192.168.115.129/<unresolved>:27001 using RedisURI [host='192.168.115.129', port=27001]
11-10 09:25:37:130 DEBUG 7512 --- [xecutorLoop-1-1] io.lettuce.core.RedisClient              : Connecting to Redis at 192.168.115.129/<unresolved>:27001
11-10 09:25:37:130 DEBUG 7512 --- [ioEventLoop-4-1] io.lettuce.core.protocol.CommandHandler  : [channel=0x340a0472, [id: 0x518c62a7] (inactive), chid=0x49] channelRegistered()
11-10 09:25:37:130 DEBUG 7512 --- [ioEventLoop-4-1] io.lettuce.core.protocol.CommandHandler  : [channel=0x340a0472, /192.168.115.1:64683 -> /192.168.115.129:27001, chid=0x49] channelActive()
11-10 09:25:37:130 DEBUG 7512 --- [ioEventLoop-4-1] i.lettuce.core.protocol.DefaultEndpoint  : [channel=0x340a0472, /192.168.115.1:64683 -> /192.168.115.129:27001, epid=0x23] activateEndpointAndExecuteBufferedCommands 0 command(s) buffered
11-10 09:25:37:130 DEBUG 7512 --- [ioEventLoop-4-1] i.lettuce.core.protocol.DefaultEndpoint  : [ch

以上是关于Linux学习-Redis哨兵的主要内容,如果未能解决你的问题,请参考以下文章

linux配置系列之redis哨兵配置

docker-compose搭建redis哨兵集群

Linux下安装配置redis详细教程,并配置哨兵模式

Day733.哨兵机制:主库挂了,如何不间断服务? -Redis 核心技术与实战

深入学习Redis:哨兵

Redis 哨兵模式核心原理