微信搜索【程序员囧辉】,关注这个坚持分享技术干货的程序员。
前言
哨兵和集群的两种高可用解决方案,但是两者在保证高可用上的实现基本是一致的,因为集群模式的高可用解决方案基本就是“照搬”哨兵模式的。
集群可以认为就是用来代替哨兵的,解决哨兵存在的一些问题,同时提供更优秀的特性。
因为现在基本不会使用到哨兵模式,哨兵模式可以说基本只存在于面试中,同时由于哨兵的内容在集群中都有类似的,所以本文对哨兵的介绍会比较简单。
正文
哨兵是什么
哨兵(Sentinel) 是 Redis 的高可用性解决方案:由一个或多个 Sentinel 实例组成的 Sentinel 系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器。
Sentinel 可以在被监视的主服务器进入下线状态时,自动将下线主服务器的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。
哨兵故障检测
检查主观下线状态
在默认情况下,Sentinel 会以每秒一次的频率向所有与它创建了命令连接的实例(包括主服务器、从服务器、其他 Sentinel 在内)发送 PING 命令,并通过实例返回的 PING 命令回复来判断实例是否在线。
如果一个实例在 down-after-miliseconds 毫秒内,连续向 Sentinel 返回无效回复,那么 Sentinel 会修改这个实例所对应的实例结构,在结构的 flags 属性中设置 SRI_S_DOWN 标识,以此来表示这个实例已经进入主观下线状态。
检查客观下线状态
当 Sentinel 将一个主服务器判断为主观下线之后,为了确定这个主服务器是否真的下线了,它会向同样监视这一服务器的其他 Sentinel 进行询问,看它们是否也认为主服务器已经进入了下线状态(可以是主观下线或者客观下线)。
当 Sentinel 从其他 Sentinel 那里接收到足够数量(quorum,可配置)的已下线判断之后,Sentinel 就会将服务器置为客观下线,在 flags 上打上 SRI_O_DOWN 标识,并对主服务器执行故障转移操作。
哨兵故障转移流程
当哨兵监测到某个主节点客观下线之后,就会开始故障转移流程。核心流程如下:
1、发起一次选举,选举出领头 Sentinel
2、领头 Sentinel 在已下线主服务器的所有从服务器里面,挑选出一个从服务器,并将其升级为新的主服务器。
3、领头 Sentinel 将剩余的所有从服务器改为复制新的主服务器。
4、领头 Sentinel 更新相关配置信息,当这个旧的主服务器重新上线时,将其设置为新的主服务器的从服务器。
选举领头哨兵
当一个主服务器被判断为客观下线时,监视这个下线主服务器的各个 Sentinel 会进行协商,选举出一个领头 Sentinel,并由领头 Sentinel 对下线主服务器执行故障转移操作。Redis 选举领头 Sentinei 的流程如下:
1、当 Sentinel 发现自己监视的主服务器进入客观下线时,会发起一次选举:将 current_epoch(集群纪元)加1,向其他监视该 master 的 Sentinel 发送拉票命令:SENTINEL is-master-down-by-addr,要求目标 Sentinel 将选票投给自己。
2、目标 Sentinel 在接收到 SENTINEL is-master-down-by-addr 命令之后,会判断自己是否已经在本届选举投过票,如果没有则会将选票投给源 Sentinel,最后回复 leader 和 leader_epoch,代表自己所投的局部领头 Sentinel 的运行ID和配置纪元。
3、源 Sentinel 收到回复后,会将目标 Sentinel 的投票信息记录下来,用于后续统计。
4、Sentinel 中同样有自己的时间事件会被定期触发,当 Sentinel 状态为:SENTINEL_FAILOVER_STATE_WAIT_START,会触发选举的投票结果统计。如果某个 Sentinel 获得超过半数以上的选票(>=voters/2+1),而且票数要大于等于 quorum,那么这个 Sentinel 将成为领头 Sentinel 。
因为领头 Sentinel 的产生需要半数以上 Sentinel 的支持,并且每个 Sentinel 在每个配置纪元里面只能投一次票 ,所以在一个配置纪元里面,只会出现一个领头 Sentinel 。
5、如果在一个配置纪元里没有一个 Sentinel 被选举为领头 Sentinel ,那么各个 Sentinel 将在一段时间之后再次进行选举,直到选出领头 Sentinel 为止。
哨兵选举主服务器
1、领头 Sentinel 会遍历已下线主节点的所有从节点,留下状态好的节点,过滤掉状态不好的节点,过滤规则主要有以下几个:
-
从节点状态为主观下线或客观下线
-
从节点链接断开
-
上次收到该从节点的正常 PING 回复超过5秒(5 * SENTINEL_PING_PERIOD)
-
从节点的优先级为0
</