Redis Sentinel执行流程

Sentinel是Redis的高可用解决方案:由一个或多个Sentinel实例组成Sentinel Cluster,可以监控任意多个master服务器,及这些master下属的slave服务器。当被监视的master进入下线状态时,Sentinel Cluster会自动将其下属的slave中的一个升级为master,然后由新的master代替已下线的master继续提供服务。

本文主要介绍Sentinel的执行流程

一. 启动并初始化Sentinel

Sentinel本质上是一个运行在特殊模式下的Redis服务器,因此它的启动方式与普通Redis类似,但是也有一些不同,其中之一就是Sentinel并不提供数据库的功能,因此不会进行持久化操作,启动时也不会根据RDB或AOF文件加载数据。

Sentinel实例启动后,会根据配置的master地址,向主服务器建立连接。每个Sentinel会创建2个连向主服务器的异步网络连接:

  1. 命令连接:这个连接专门用于向主服务器发送命令,并接收响应;
  2. 订阅连接:这个连接专门用于订阅主服务器的_sentinel_:hello 这个Channel。

二. 获取主服务器信息

Sentinel默认每10s一次,向被监控的主服务器发送info命令,获取主服务器和其下属从服务器的信息。

三. 获取从服务器信息

当Sentinel发现主服务器有新的从服务器出现时,Sentinel还会向从服务器建立命令连接和订阅连接。在命令连接建立之后,Sentinel还是默认10s一次,向从服务器发送info命令,并记录从服务器的信息。

四. 向主服务器和从服务器发送消息

默认情况下,Sentinel每2s一次,向所有被监视的主服务器和从服务器所订阅的_sentinel_:hello频道上发送消息,消息中会携带Sentinel自身的信息和主服务器的信息。

五. 接收来自主服务器和从服务器的频道信息

多个监控同一个主服务器的Sentinel,都会发送频道消息,这样其他的Sentinel就都会接收到。Sentinel集群中的各个节点,通过频道消息感知彼此的存在。

当Sentinel通过频道消息感知到一个新的Sentinel加入时,就会创建一个新的连接连向这个新的Sentinel,同样新的Sentinel也会与所有已经存在的Sentinel建立连接。最终,监控同一个主服务器的多个Sentinel就构成了一个相互连接的网络,他们之间就会可以命令连接进行通信。

Sentinel彼此之间只创建命令连接,而不创建订阅连接,因为Sentinel通过订阅主服务器或从服务器,就可以感知到新的Sentinel的加入,而一旦新Sentinel加入后,相互感知的Sentinel通过命令连接来通信就可以了。

六. 检测主观下线状态

默认情况下,Sentinel每秒一次向所有与它建立了命令连接的实例(包括主服务器、从服务器和其他Sentinel)发送PING命令,并根据回复判断实例是否在线。如果在Sentinel配置文件中的down-after-milliseconds毫秒内,连接向Sentinel返回无效回复,那么Sentinel就会认为该实例主观下线(SDown)

七. 检查客观下线状态

当一个Sentinel将一个主服务器判断为主观下线后,为了确认是否真的下线,这个Sentinel会向同时监控这个主服务器的所有其他Sentinel发送查询命令,判断它们是否也任务主服务器下线(包括主观下线和客观下线)。如果达到Sentinel配置中的quorum数量的Sentinel实例都判断主服务器为主观下线,则该主服务器就会被判定为客观下线。

八. 选举Leader Sentinel

当一个主服务器被判定为客观下线后,监视这个主服务器的所有Sentinel会通过选举算法,选出一个Leader Sentinel去执行failover操作。

九. 故障转移

当选举出Leader Sentinel后,Leader Sentinel会对下线的主服务器执行故障转移操作,主要有一下三个步骤:

  1. 在已下线的主服务器的所有下属从服务器中,选举出一个作为新的主服务器。
  2. 将所有从服务器改为复制新的主服务器。
  3. 将已下线的主服务器设置为新的主服务器的从服务器。

在从服务器列表在选举出新的主服务器,需经过以下流程:

  1. 删除列表中下线或者断线状态的实例。
  2. 删除列表中最近5s没有回复Leader Sentinel INFO信息的实例。
  3. 删除与主服务器断开时间超过down-after-milliseconds的实例,确保剩余的从服务器的数据都是比较新的。
  4. 根据设置的优先级,选择优先级最高的从服务器。
  5. 如果优先级相同,则比较从服务器的复制偏移量(偏移量最大的从服务器中的数据是最新的)。
  6. 如果复制偏移量也相同,那么选择runId最小的从服务器。