Redis(七) 哨兵

Posted by ZhouJ000 on November 16, 2018
最后更新于:2018-11-21

Redis(一) 基础与api
Redis(二) 小功能
Redis(三) 阻塞与内存
Redis(四) 缓存设计
Redis(五) 客户端调用
Redis(六) 持久化与复制
Redis(七) 哨兵
Redis(八) 集群

哨兵

redis的主从复制模式下,一旦主节点由于出现故障不能提供服务,需要将从节点晋升为主节点,同时还要通知应用方更新主节点地址。redis提供了Redis Sentinel(哨兵)架构来解决这个问题

Redis Sentinel是一个分布式架构,其中包含若干个Sentinel节点和Redis数据节点,每个Sentinel节点会对数据节点和其余Sentinel节点进行监控,当发现节点不可达时,会对节点做下线标识。如果被标识的是主节点,它还会和其他Sentinel节点进行”协商“,当大多数Sentinel节点都认为主节点不可达时,它们会选举出一个Sentinel节点来完成自动故障转移的工作,同时还会将这个变化实时通知给redis应用方

Redis Sentinel与Redis主从复制模式只是多了若干个Sentinel节点,所以Redis Sentinel并没有针对Redis节点做特殊处理。从逻辑架构上看,Sentinel节点集合会定期对所有节点进行监控,特别是对主节点的故障实现自动转移

整个故障转移的处理逻辑:
1、主节点出现故障,此时从节点与主节点失去连接,主从复制失败
2、每个Sentinel节点通过定期监控发现主节点出现故障
3、多个Sentinel节点对主节点的故障达成一致,选举出某个Sentinel节点作为领导者负责故障转移
4、Sentinel领导者节点执行了故障转移

可以看出Redis Sentinel具有以下功能:监控、通知、主节点故障转移、配置提供者

安装和部署

一主两从,三个Sentinel节点(一般至少3个,3台以下如果1台哨兵也宕机了,会导致majority不满足)

主节点:

port 6379
daemonize yes
logfile "6379.log"
dbfilename "dump-6379.rdb"
dir "/opt/redis/data/"

启动主节点:redis-server redis-6379.conf

从节点:

port 6380
daemonize yes
logfile "6380.log"
dbfilename "dump-6380.rdb"
dir "/opt/redis/data/"
slaveof 127.0.0.1 6379

启动从节点:redis-server redis-6380.conf

确定主从关系:redis-cli -h 127.0.0.1 -p 6379 info replicationredis-cli -h 127.0.0.1 -p 6380 info replication

Sentinel节点:

port 26379
daemonize yes
logfile "26379.log"
dir "/opt/redis/data/"
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000

启动sentinel节点:redis-sentinel redis-sentinel-26379.confredis-server redis-sentinel-26379.conf --sentinel

确认Sentinel节点:redis-cli -h 127.0.0.1 -p 26379 info Sentinel

API

1、sentinel masters:展示所有被监控主节点状态以及相关的统计信息

2、sentinel master <master name>:展示指定主节点状态及相关统计信息

3、sentinel slaves <master name>:展示指定主节点的从节点状态以及相关的统计信息

4、sentinel sentinels <master name>:展示指定主节点的Sentinel节点集合(不包含当前Sentinel节点)

5、sentinel get-master-addr-by-name <master name>:返回指定主节点的IP地址和端口

等等

客户端连接

1、遍历sentinel节点集合获取一个可用的sentinel节点
2、通过sentinel get-master-addr-by-name master-name这个API获取对应主节点的相关信息
3、验证当前获取的主节点是否是真正的主节点,是为了防止故障转移期间主节点的变化

Jedis操作

JedisSentinelPool的构造方法里,initSentinels初始化方法非常重要,就是按上面步骤原理实现的

JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(masterName, sentinelSet, poolConfig, timeout);

Jedis jedis = null;
try {
	jedis = jedisSentinelPool.getResource();
	// jedis command
} catch(Exception e){
} finally {
	if (jedis != null) {
		jedis.close();
	}
}

实现原理

三个定时监控任务

一套合理的监控机制是Sentinel节点判定节点不可达的重要保证,Redis Sentinel通过三个定时监控任务完成对各个节点发现和监控

1、每隔10秒,每个Sentinel节点会向主节点和从节点发送info命令获取最新的拓扑结构。其作用主要体现在:通过向主节点执行info信息,获取从节点信息,所以Sentinel节点不需要显示配置监控从节点;当有新节点加入都可以立即感知;节点不可达或故障转移后可以立即通过info命令实时更新节点拓扑信息

2、每隔2秒,每个Sentinel节点会向Redis数据节点的__sentinel__:hello频道上发送该Sentinel节点对于主节点的判断以及当前Sentinel节点的信息,同时每个Sentinel节点也会订阅该频道,来了解其他Sentinel节点以及它们对主节点的判断。这个任务主要完成:发现新的Sentinel节点,Sentinel节点之间交换主节点的状态,作为后面客观下线以及领导者选举的依据

3、每隔1秒,每个Sentinel节点会向主节点、从节点、其余Sentinel节点发送一条ping命令作为一次心跳检测,来确定这些节点是否可达

主观下线和客观下线

每隔1秒的定时任务,发送ping命令做心跳检测,当这些节点超过down-after-milliseconds没有进行有效回复,Sentinel节点就会对该节点做失败判定,这个行为叫主观下线。可以看出是当前Sentinel一家之言,存在误判的可能

当Sentinel主观下线的节点是主节点时,该Sentinel节点会通过sentinel is-master-down-by-addr命令向其他Sentinel节点询问对该主节点的判断,当超过{quorum}个数,Sentinel节点认为主节点确实有问题,这时该Sentinel节点会做出客观下线的决定

领导者Sentinel节点选举

假如Sentinel节点对主节点做出了客观下线,不会立即进行故障转移。实际上故障转移的工作只需要一个Sentinel节点来完成即可,所以Sentinel节点之间会做一个领导者选举的工作,选出一个Sentinel节点作为领导者进行故障转移的工作。Redis采用了Raft算法实现领导者选举

领导选举大致思路:
1、每个在线Sentinel节点都有资格成为领导者,当它确认主节点主观下线时,会向其他Sentinel节点发送sentinel is-master-down-by-addr命令,要求将自己设置为领导者
2、收到命令的Sentinel节点,如果没有同意过其他Sentinel节点的sentinel is-master-down-by-addr命令,将同意该请求,否则拒绝
3、如果该Sentinel节点发现自己的票数已经大于max(quorum, num(sentinels)/2 + 1),那么它将成为领导者
4、如果此过程没有选举出领导者,将进行下一轮选举

选举的过程非常快,基本上谁先完成客观下线,谁就是领导者

故障转移

Sentinel领导者节点负责故障转移:

  1. 在从节点列表中选举出一个节点作为新的主节点
    • 过滤:”不健康”(主观下线、断线)、5秒内没有回复过Sentinel节点ping响应、与主节点失联超过down-after-milliseconds*10秒
    • 选择slave-priority(从节点优先级)最高的从节点列表,如果存在则返回,不存在则继续
    • 选择复制偏移量最大的从节点(复制最完整),如果存在返回,不存在继续
    • 选择runid最小的从节点
  2. Sentinel领导者节点会对第一步选出来的从节点执行slaveof no one命令让其成为主节点
  3. Sentinel领导者节点会向剩余的从节点发送命令,让它们成为新主节点的从节点,复制规则和parallel-syncs参数有关
  4. Sentinel节点集合会将原来的主节点更新为从节点,并保持着对其关注,当其恢复后命令它去复制新的主节点

问题

故障转移日志

部署各个节点的机器时间尽量要同步,否则日志的时序性会混乱,例如可以给机器添加NTP服务来同步时间

节点运维

节点下线:临时下线和永久下线

节点上线

节点配置

高可用读写分离

从节点的作用:当主节点出现故障时,作为主节点的后备;扩展主节点的读能力。从节点不是高可用的,出现故障后Sentinel节点只会对该节点做主观下线,因为Redis Sentinel的故障转移是针对主节点的

Redis Sentinel在对各个节点的监控中,如果有对应事件的发生,都会发出相应的事件消息,其中和从节点变动有关的有:+switch-master切换主节点、+convert-to-slave切换从节点、+sdown主观下线、+reboot重新启动了某个节点

所以在设计Redis Sentinel从节点高可用时,只要能够实时掌握所有从节点的状态,把所有从节点看成一个资源池,无论是上线还是下线从节点,客户端都能感知到(将其从资源池中添加或删除),这样从节点的高可用目标就达到了