Redis哨兵机制

哨兵机制

主从库的集群模式使得当从库发生故障以后,客户端可以继续向主库或者其他从库发送请求,进行相关的操作;但是如果主库发生了故障,那会直接影响到从库的同步。无论是写中断还是从库无法进行数据同步都是Redis所不能接受的。因此我们需要一些机制,来能够将一个从库切换为主库,这就涉及到了Redis的哨兵机制。

1. 哨兵机制的基本流程

  • 哨兵可以理解为一个运行在特殊模式下的Redis进程,其在主从库实例运行的同时也在运行
  • 哨兵主要的三个任务为:
    • 监控 — 决策:判断主库是否处于下线状态
      • 周期性的ping主库,检测其是否仍然在线运行
      • 如果从库没有在规定时间内响应哨兵的Ping命令,哨兵就会将其标记为下线状态
      • 对主库来说同理,在判定主库下线以后会开始一个自动切换主库的流程
    • 选主 — 决策:决定选择哪个从库实例作为主库
      • 主库挂了以后,哨兵就需要从很多歌从库里按照一定的规则选择一个从库实例,将其作为新的主库
    • 通知
      • 将新主库的连接信息发给其他从库,让它们执行replicaof命令,与新主库建立连接,并进行数据复制
      • 哨兵会将新主库的连接信息通知给客户端,让它们将请求操作发到新主库当中

哨兵三大任务

2. 判断主库的下线状态

2.1 哨兵集群使用原因

2.1.1 为什么需要哨兵集群?

  • 如果哨兵发生误判,后续的选主和通知操作都会带来额外的计算和通信的开销
  • 误判通常发生在
    • 集群网络压力较大
    • 网络拥塞
    • 主库本身压力较大的情况
  • 哨兵机制也是类似的,它通常会采用多实例组成的集群模式进行部署,这也被称为哨兵集群。引入多个哨兵实例一起来判断,就可以避免单个哨兵因为自身网络状况不好,而误判主库下线的情况。同时,多个哨兵的网络同时不稳定的概率较小,由它们一起做决策,误判率也能降低。

2.1.2 如何使用哨兵集群?

  • 简单来说,“客观下线”的标准就是,当有 N 个哨兵实例时,最好要有 N/2 + 1 个实例判断主库为“主观下线”,才能最终判定主库为“客观下线”。这样一来,就可以减少误判的概率,也能避免误判带来的无谓的主从库切换。(当然,有多少个实例做出“主观下线”的判断才可以,可以由 Redis 管理员自行设定)。

2.2 哨兵集群原理 — 基于PubSub机制

2.2.1 pubsub机制

哨兵实例之间的相互发现是基于Redis提供的pubsub机制的,哨兵只要和主库建立起连接,就可以在主库上发布消息了

  • 可以选择发布自己的连接信息到主库上
  • 也可以从主库上订阅消息,获得其他哨兵发布的连接信息
  • 当多个哨兵实例都在主库上做了发布和订阅操作之后,他们之间就能知道彼此的IP地址和端口

2.2.2 频道

  • Redis通过频道来区分不同应用的消息,对这些消息进行分门别类的管理。频道就是指消息的类别,当消息类别相同时,就会属于同一个频道,否则属于不同的频道。
  • 只有订阅了同一个频道的应用,才能通过发布的消息进行信息交换

频道订阅机制

  • 哨兵1 想频道hello发送信息,因为哨兵2 哨兵3 subscribe了hello频道,他们就能从这个频道获取到哨兵1的IP地址和端口号信息

2.2.3 哨兵和从库的连接沟通

  • 哨兵向主库发出INFO命令

  • 主库收到命令后,就会将从库列表返回给哨兵

  • 接着哨兵就可以根据从库列表中的信息,和每个从库建立连接,并在这个连接上持续对从库进行监控

    哨兵和从库的连接

  • 哨兵除了上述的和主库之间的连接,获取从库列表,并和从库们建立连接之外,还承担着在发生主库更换以后,将新主库的信息告诉客户端这个任务

2.3 客户端事件通知机制

  • 哨兵是一个运行在特定模式下的Redis实例,只是它不服务请求操作,只是完成监控,选主和通知的任务

  • 因此每个哨兵实例也提供pubsub机制,客户端可以从哨兵订阅消息

    • 哨兵提供了很多的消息订阅频道,不同频道包含了主从库切换过程中的不同关键事件

      常用的关键时间列表

    • 客户端可以执行订阅命令,来订阅不同的频道,然后来获取不同的事件信息

3. 如何选定新主库?

  • 筛选
    • 确保从库仍然在线运行
    • 判断其之前的网络状态 看该从库和主库之间是否经常断联,出现网络相关的问题
  • 打分 — 只要有得分最高的,那么就在当前轮停止并且认定其为主库
    • 从库优先级
      • 用户可以通过slave-priority配置项,给不同的从库设置不同的优先级
        • 譬如:两个从库内存大小不一样,我们就可以手动给内存大的实例设置一个高优先级
    • 从库复制进度
      • 选择和旧主库同步最为接近的那个从库作为主库
      • 如何判断从库和旧主库的同步进度?
        • 主从库之间命令传播机制里面的master_repl_offset 和slave_repl_offset
        • 看二者的接近程度
    • 从库ID号
      • 当优先级和复制进度都相同的情况下,ID号最小的从库得分最高,被选为新主库

4. 由哪个哨兵来执行主从切换?

  • 任何一个实例只要自身判断主库主观下线之后,就会给其他势力发送is-master-down-by-addr命令。接着其他实例会根据自己和主库的连接情况,做出Y或N的响应

      ![is master down by addr](https://i.loli.net/2021/01/11/HpT5MAdKX9fmo2S.png)
    • 一个哨兵获得了仲裁所需的赞成票数后,就可以标记主库为客观下线

      • 这个所需的赞成票数是通过哨兵配置文件中的quorum配置项设定的
    • 当获得了所需赞成票数以后,这个哨兵会再给其他哨兵发送命令,希望由自己来执行主从切换,并让所有其他哨兵进行投票,这个过程称为Leader选举。

    • 在投票过程中,任何一个想成为 Leader 的哨兵,要满足两个条件:第一,拿到半数以上的赞成票;第二,拿到的票数同时还需要大于等于哨兵配置文件中的 quorum 值。以 3 个哨兵为例,假设此时的 quorum 设置为 2,那么,任何一个想成为 Leader 的哨兵只要拿到 2 张赞成票,就可以了。

    • 票选执行主从切换哨兵的过程

    1. 在 T1 时刻,S1 判断主库为“客观下线”,它想成为 Leader,就先给自己投一张赞成票,然后分别向 S2 和 S3 发送命令,表示要成为 Leader。
    2. 在 T2 时刻,S3 判断主库为“客观下线”,它也想成为 Leader,所以也先给自己投一张赞成票,再分别向 S1 和 S2 发送命令,表示要成为 Leader。
    3. 在 T3 时刻,S1 收到了 S3 的 Leader 投票请求。因为 S1 已经给自己投了一票 Y,所以它不能再给其他哨兵投赞成票了,所以 S1 回复 N 表示不同意。同时,S2 收到了 T2 时 S3 发送的 Leader 投票请求。因为 S2 之前没有投过票,它会给第一个向它发送投票请求的哨兵回复 Y,给后续再发送投票请求的哨兵回复 N,所以,在 T3 时,S2 回复 S3,同意 S3 成为 Leader。
    4. 在 T4 时刻,S2 才收到 T1 时 S1 发送的投票命令。因为 S2 已经在 T3 时同意了 S3 的投票请求,此时,S2 给 S1 回复 N,表示不同意 S1 成为 Leader。发生这种情况,是因为 S3 和 S2 之间的网络传输正常,而 S1 和 S2 之间的网络传输可能正好拥塞了,导致投票请求传输慢了。
    5. 在 T5 时刻,S1 得到的票数是来自它自己的一票 Y 和来自 S2 的一票 N。而 S3 除了自己的赞成票 Y 以外,还收到了来自 S2 的一票 Y。此时,S3 不仅获得了半数以上的 Leader 赞成票,也达到预设的 quorum 值(quorum 为 2),所以它最终成为了 Leader。接着,S3 会开始执行选主操作,而且在选定新主库后,会给其他从库和客户端通知新主库的信息。
    • 如果 S3 没有拿到 2 票 Y,那么这轮投票就不会产生 Leader。哨兵集群会等待一段时间(也就是哨兵故障转移超时时间的 2 倍),再重新选举。这是因为,哨兵集群能够进行成功投票,很大程度上依赖于选举命令的正常网络传播。如果网络压力较大或有短时堵塞,就可能导致没有一个哨兵能拿到半数以上的赞成票。所以,等到网络拥塞好转之后,再进行投票选举,成功的概率就会增加。需要注意的是,如果哨兵集群只有 2 个实例,此时,一个哨兵要想成为 Leader,必须获得 2 票,而不是 1 票。所以,如果有个哨兵挂掉了,那么,此时的集群是无法进行主从库切换的。因此,通常我们至少会配置 3 个哨兵实例。

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 stone2paul@gmail.com

文章标题:Redis哨兵机制

文章字数:2.6k

本文作者:Leilei Chen

发布时间:2021-01-06, 20:07:59

最后更新:2021-01-10, 10:04:18

原始链接:https://www.llchen60.com/Redis%E5%93%A8%E5%85%B5%E6%9C%BA%E5%88%B6/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏