哨兵(Sentinel)

Sentinel是Redis的高可用性(high availability)解决方案:由一个或多个Sentinel实例组成的Sentinel系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。

一、主从复制存在的问题

Redis的主从复制模式将数据改变同步到从节点,做数据的备份以及扩展主节点的读能力。

但该模式存在一个问题:一旦主节点出现故障,需要手动将某个从节点晋升为主节点,同时需要修改应用方的主节点地址,还需要命令其他从节点去复制新节点。整个过程需要人工干预。

二、Redis Sentinel的高可用性

当主节点出现故障时,Redis Sentinel能自动完成故障发现和故障转移,并通知应用方从而实现真正的高可用。

整个步骤为:

  • 主节点出现故障,所有从节点与主节点失去连接,主从复制失败
  • 每个Sentinel节点通过定期监控发现主节点出现了故障
  • 多个Sentinel节点对主节点的故障达成一致,选举出某个Sentinel节点作为领导者负责故障转移
  • Sentinel领导者执行故障转移,整个过程与人工干预一致,唯一区别是自动化完成

三、实现原理

1.三个定时监控任务

  • 每隔10s,每个Sentinel节点会向主节点和从节点发送info命令获取最新的拓扑结构。作用:
    • 向主节点发送info,获取从节点信息
    • 当有新的从节点加入时都可以立刻感知出来
    • 节点不可达或者故障转移后,可实时更新节点拓扑信息
  • 每隔2s,每个Sentinel节点会想Redis数据节点的_sentinel_:hello频道上发送该Sentinel节点对于主节点的判断以及当前Sentinel节点的信息,同时每个Sentinel节点会订阅该频道,来了解其他Sentinel节点以及它们对主节点的判断。
  • 每隔1s,每个Sentinel节点会向主节点、从节点、其余Sentinel节点发送一条ping命令做心跳检测,来确认节点是否可达。

2.主观下线和客观下线

  • 主观下线:Sentinel会以每秒一次的频率向所有与它创建了命令连接的实例发送ping命令。如果一个实例在down-after-milliseconds毫秒内,连续向Sentinel返回无效回复,那么Sentinel会修改这个实例对应的实例结构,在结构的flags属性中打开SRISDOWN标识,以表示这个实例已经进入主观下线状态。
  • 客观下线:当Sentinel将一个主服务器判断为主观下线后,会向同样监视这一主服务器的其他Sentinel进行询问,看他们是否也认为主服务器已经进入了下线状态。当Sentinel从其他Sentinel那里接收到足够数量的已下线判断之后,Sentinel就会将主服务器判定为客观下线,并对主服务器执行故障转移操作。

3.Sentinel领导者选举

Sentiel使用Raft算法实现领导者选举。 大致过程:

  • 每个在线的Setinel节点都有资格成为领导者,当它确认主节点主观下线时候,会向其他Setinel节点发送sentinel is-master-down-by-addr命令,要求将自己设置为领导者;
  • 收到命令的Sentinel节点,如果没有同意过其他Sentinel节点的sentinel is-master-down-by-addr命令,将同意该请求,否则拒绝;
  • 如果该Sentinel节点发现自己的票数已经大于等于一半,那么它将成为领导者
  • 如果没有选举出领导者,将进入下一次选举(不论是否成功,配置纪元都会自增一次)

4.故障转移

  • 在从节点列表中选出一个节点作为新的主节点
    • 过滤:主线下线、断线、5秒内没有回复过Sentinel节点ping响应、与主节点失联超过down-after-milliseconds*10
    • 选择slave-priority最高的从节点列表,如果存在则返回,不存在则继续
    • 选择复制偏移量最大的从节点,如果存在则返回,不存在则继续
    • 选择 runid 最小的从节点
  • Sentinel领导者节点会对选出的新的主节点执行slaveof no one 命令让其成为主节点
  • Sentinel领导者节点会向剩余的从节点发送命令,让他们成为新的主节点的从节点
  • Sentinel节点集合会将原来的主节点更新为从节点,并保持对其关注,当其恢复后命令它去复制新的主节点