Redis Sentinel

Redis Sentinel

Sentinel(哨兵 在Redis 2.8版本开始引入)哨兵的核心功能是主节点的自动故障转移。他是一个Redis的高可用性解决方案:由一个或多个Sentinel实例组成的Sentinel系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器。并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器省纪委新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。

Redis Sentinel的功能描述

  • 监控(Monitoring):哨兵会不断地检查主节点和从节点是否运作正常。
  • 自动故障转移(Automatic failover):当主节点不能正常工作时,哨兵会开始自动故障转移操作,它会将失效主节点的其中一个从节点升级为新的主节点,并让其他从节点改为复制新的主节点。
  • 配置提供者(Configuration provider):客户端在初始化时,通过连接哨兵来获得当前Redis服务的主节点地址。
  • 通知(Notification):哨兵可以将故障转移的结果发送给客户端。

Sentinel.jpeg

客户端连接Redis Sentinel

Jedis客户端对Redis Sentinel提供了很好的支持。我们只需要向Jedis提供Sentinel节点集合和masterName,构造JedisSentinelPool对象(与JedisPool区分开来),然后便可以像使用普通redis连接池一样来使用了:通过pool.getResource()获取连接,执行具体的命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void testSentinel() throws Exception {
String masterName = "mymaster";
Set<String> Sentinels = new HashSet<>();
Sentinels.add("192.168.92.128:26379");
Sentinels.add("192.168.92.128:26380");
Sentinels.add("192.168.92.128:26381");

JedisSentinelPool pool = new JedisSentinelPool(masterName, Sentinels); //初始化过程做了很多工作
Jedis jedis = null
try {
pool.getResource();
jedis.set("key1", "value1");
}
finally{
pool.close();
}
}

客户端的高可用

  1. Sentinel结点集合 + masterName去遍历Sentinel集合,找到可用的Sentinel结点
  2. 在第一步的结点上执行 Sentinel get-master-addr-by-name masterName 会返回 master 结点的地址以及端口
  3. 当第二部获取到master结点后会进行 role或者role replication进行验证是否是master结点
  4. 如果master发生了变化,Sentinel是感知的,因为故障发现和故障转移都是由Sentinel来执行的。Sentinel和客户端是用一种发布订阅的模式,客户端订阅Sentinel的某一个频道,里面有master的变化信息,如果存在master变化,Sentinel会publish一条消息,客户端就可以获取再对新的master进行一个连接。

Sentinel服务端高可用

Sentinel服务端高可用分为三个定时任务、主观下线和客观下线、领导者选举、故障转移

三个定时任务

  • 10秒每个Sentinel对master和slave执行info,以此发现slave节点并确认主从关系。

    • 发现slave结点
    • 确认主从关系
  • 2秒每个Sentinel通过master节点的channel交换信息(pub/sub)。

    • 通过Sentinel:hello频道交互
    • 交互对结点的“看法”和自身信息
  • 每1秒每个Sentinel对其它Sentinel和redis执行ping也就是心跳检测。

    • 心跳检测,失败判定的依据

主观下线和客观下线

主观下线和客观下线涉及两条配置

1
2
3
Sentinel monitor <masterName> <ip> <port> <quorum>

Sentinel down-after-milliseconds <masterName> <timeout>

其中quorum为法定人数down-after-milliseconds为心跳检测的超时时间

主观下线:每个Sentinel结点对Redis结点失败的“偏见”,如果在down-after-milliseconds设定的时间都没有回复,则“主观地”判断下线。

客观下线:主观下线后,过Sentinel is-master-down-by-addr命令询问其他哨兵节点该主节点的状态。如果判断该结点下线的Sentinel结点超过quorum(建议是节点数的一半+1)则对该主节点进行客观下线。

需要特别注意的是,客观下线是主节点才有的概念,如果从节点和哨兵节点发生故障,被哨兵主观下线后,不会再有后续的客观下线和故障转移操作因为只有主节点才需要进行故障转移。

领导者选举

由于故障转移只需要一个Sentinel结点来完成。所以需要选举一个Sentinel来进行故障后咋偶难以。

通过Sentinel is-master-down-by-addr命令都希望成为领导者

  1. 每个做主观下线的Sentinel结点向其他结点发送命令,要求将他设置为领导者
  2. 收到命令的Sentinel及诶单如果没有同意通过其他Sentinel及诶单发送的命令,那么将同意该请求,否则拒绝。
  3. 如果该Sentinel结点发现自己的票数已经超过了Sentinel半数且超过quorum,那么它将成为领导者。
  4. 如果此过程有多个Sentinel结点成为了领导者,那么等待一段时间重新进行选举。

故障转移

  1. 从slave结点选取一个“合适的”结点作为新的master结点
  2. 对上面的slave及诶单执行 slaveof no one 命令让它成为master结点
  3. 向剩余的slave结点发送命令,让它们成为新master结点的slave结点,复制规则和parallel-syncs参数有关
  4. 更新原来master节点配置为slave,并保持着对其“关注”,当其恢复后命令它去复制新的master节点。

选择“合适的”slave结点

  1. 选择slave-priority(slvae结点优先级)最高的slave结点,如果存在则返回,不存在则继续(一般不配置,或者配置成机器配置较高的)
  2. 选择复制偏移量最大的slave结点(复制的最完整),如果存在则返回,不存在则继续
  3. 选择run ID最小的slave结点(启动最早的结点)

参考资料

  • Redis设计与实现 黄健宏 机械工业出版社

  • Redis开发与运维 付磊 / 张益军 机械工业出版社