[Redis][16][Sentinel]

第 16 章 Sentinel

Sentinel(哨兵)是Redis的高可用性解决方案

  • 由一个或多个Sentinel实例组成的Sentinel系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器
  • 并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,

下面举个例子说明为什么Sentinal可以保证高可用

首先,我们假设有这样一个系统,如下图,它由sentinel系统、一个主服务器和三个从服务器组成

假设这时,主服务下线,则Sentinel系统可以察觉到它的下线

当主服务器下线事件过长,Sentinel系统就会进行故障转移操作

  • 首先,Sentinel系统会挑选server1属下的其中一个从服务器,并将这个被选中的从服务器升级为新的主服务器。
  • 之后,Sentinel系统会向server1属下的所有从服务器发送新的复制指令,让它们成为新的主服务器的从服务器,当所有从服务器都开始复制新的主服务器时,故障转移操作执行完毕。
  • 另外,Sentinel还会继续监视已下线的server1,并在它重新上线时,将它设置为新的主服务器的从服务器。

之后,如果server1重新上线的话,它将被Sentinel系统降级为server2的从服务器

16.1 启动并初始化Sentinel

使用下面的命令,可以启动一个Sentinel

1
redis-server /path/to/your/sentinel.conf --sentinel

当一个Sentinel启动时,它需要执行下面几步

  1. 初始化服务器:这一步只是初始化一个普通的Redis服务器

  2. 将普通Redis服务器使用的代码替换成Sentinel专用代码:例如,普通Redis的命令表与Sentinel的命令表区别很大,这一步要使用Sentinel专用的命令表替换Redis命令表

  3. 初始化Sentinel状态:它会创建一个sentinelState结构来保存与sentinel功能相关的一些状态

  4. 初始化Sentinel的监视主服务器列表:它会根据配置文件,创建Sentinel要监控的一些主服务器

  5. 创建连向主服务器的网络连接,对于每个被监视的主服务器,Sentinel会创建两个连接

    • 一个是命令连接,这个连接专门用于向主服务器发送命令,并接收命令回复。
    • 另一个是订阅连接,这个连接专门用于订阅主服务器的__sentinel__:he11o频道。

16.2 获取主服务器信息

Sentinel默认会以每十秒一次的频率,通过命令连接向被监视的主服务器发送INFO命令,并通过分析INFO命令的回复来获取主服务器本身的信息以及与主服务器关联的从服务器信息。

16.3 获取从服务器信息

通过上一步,Sentinel就可以得知主服务器下属的从服务器,然后Sentinel不但会保存这些从服务器信息,还会创建到从服务器的命令连接和订阅连接

在建立连接之后,Sentinel也会按照每十秒一次的频率向从服务器发送INFO命令,根据回复来维护从服务器的状态

16.4 订阅连接的作用

每当建立起订阅连接之后,Sentinel就会发送下面的命令,来监听主服务的__sentinel__:hello频道。

Sentinel会每隔两秒钟向这个频道发送下面格式的消息,这条消息主要包含了sentinel节点自身的信息和主服务器信息

1
PUBLISH __sentinel__:hello "<s_ip>,<s_port>,<s_runid>,<s_epoch>,<m_name>,<m_ip>,<m_port>,<m_epoch>"

然后以主服务器为跳板,其他Sentinel节点也会收到这个消息,因为所有的监视这个主服务器的Sentinel节点都会订阅这个频道,如下图

然后通过这种机制,监听同一个主服务器的Sentinel节点就可以自动发现对方了

当某个Sentinel节点通过接收到__sentinel__:hello频道发送的消息发现了其他节点,它就会存储这个节点的信息,并且建立与这个节点的命令连接,如下图。实际上Sentinel系统中的所有Sentinel节点之间都有命令连接,它们可以互相通信

16.6 检测主观下线状态

每一秒,Sentinel都会向所有与它创建了连接的节点(包括主服务器、从服务器、其他Sentinel)发送PING命令,来判断对方是否在线。

若一段时间内,某个节点始终没有有效回应,它就会被标记为下线,flags属性将开启SRI_S_DOWN标记,表示这个实例进入了主观下线状态

16.7 检查客观下线状态

当Sentinel节点将一个主服务器判断为主观下线,它就会向其他Sentinel节点发送询问,看看其他节点是否也同样认为主服务器下线。

Sentinel使用下面的命令询问其他Sentinel节点的意见

1
SENTINEL is-master-down-by-addr <ip><port><current_epoch><runid>

然后这个Sentinel节点就会接受其他节点的返回结果,如果有超过N个节点也这么认为,那么这个Sentinel节点就会将主服务器标注为客观下线,并开始选举领头Sentinel。

16.8 选举领头Sentinel

当一个主服务器被判定为客观下线后,Sentinel节点就会开始协商,选举出一个领头Sentinel,由它来进行故障转移

以下是选举规则

  1. 所有在线的Sentinel节点都由被选为领头Sentinel的资格
  2. 每次进行领头Sentinel选举之后,所有Sentinel节点的配置纪元(epoch)就会自增一位,它是个计数器,用来判断选举的轮次
  3. 在每个选举轮次中,也就是在每个配置纪元中,每个发现主服务器客观下线的Sentinel节点都会要求其他节点将自己设置为局部领头节点,我们称这些要当领头节点的节点为源节点
  4. 然后根据先到先得的原则,假设有源节点A、源节点B都发送了选举信息给目标节点C,则C会设置先到达的为局部领头节点,并告知这两个源节点自己的想法
  5. 这样每个源节点都会得知目标节点们的意见,如果有个源节点发现自己获得了半数以上的支持,它就会从局部领头节点变为领头节点,然后执行故障转移
  6. 若本轮没有一个源节点得到半数支持,那么隔一段时间重新选举

16.9 故障转移

然后领头Sentinel节点将,进行故障转移操作

  • 首先,领头Sentinel节点会挑选server1属下的其中一个从服务器,并将这个被选中的从服务器升级为新的主服务器。
  • 之后,领头Sentinel节点向server1属下的所有从服务器发送新的复制指令,让它们成为新的主服务器的从服务器,当所有从服务器都开始复制新的主服务器时,故障转移操作执行完毕。
  • 另外,Sentinel还会继续监视已下线的server1,并在它重新上线时,将它设置为新的主服务器的从服务器。

16.10 重点回顾

  • Sentinel只是一个运行在特殊模式下的Redis服务器,它使用了和普通模式不同的命令表
  • Sentinel会读入用户指定的配置文件,为每个要被监视的主服务器创建相应的实例结构,并创建连向主服务器的命令连接和订阅连接
  • Sentinel通过向主服务器发送INFO命令来获得主服务器属下所有从服务器的地址信息,然后与从服务器建立连接
  • 对于监视同一个主服务器和从服务器的多个Sentinel来说,它们会以每两秒一次的频率,通过向被监视服务器的__sentinel__:he11o频道发送消息来向其他Sentinel宣告自己的存在。
  • 每个Sentinel也会从__sentinel__:he11o频道中接收其他Sentinel发来的信息,并根据这些信息为其他Sentinel创建相应的实例结构,以及命令连接。
  • Sentinel以每秒一次的频率向实例(包括主服务器、从服务器、其他 Sentinel)发送PING命令,并根据实例对PING命令的回复来判断实例是否在线,当一个实例在指定的时长中连续向Sentinel发送无效回复时, Sentinel会将这个实例判断为主观下线。
  • 当Sentinel将一个主服务器判断为主观下线时,它会向同样监视这个主服务器的其他Sentinel进行询问,看它们是否同意这个主服务器已经进入主观下线状态。
  • 当Sentinel收集到足够多的主观下线投票之后,它会将主服务器判断为客观下线,并发起一次针对主服务器的故障转移操作。

此外,Sentinel系统选举领头节点的方法是对Raft算法的领头选举方法的实现