Redis核心技术与实战-学习笔记(八)哨兵集群:哨兵挂了

         一旦多个实例组成了哨兵集群,即使有哨兵实例出现故障挂掉了,其他哨兵还能继续协作完成主从库切换的工作,包括判定主库是不是处于下线状态,选择新主库,以及通知从库和客户端。

在配置哨兵信息时,只需要用到下面的配置项,设置主库IP和端口,并没有配置其他哨兵的连接信息。

sentinel monitor <master-name> <ip> <redis-port> <quorum>

基于pub/sub机制的哨兵集群组成

          哨兵实例之间可以相护发现,要归功于Redis提供的pub/sub机制,也就是发布/订阅机制

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

Redis会以频道的形式,对消息进行分门别类的管理。类似于消息队列的主题

只有订阅了同一频道的应用,才能通过发布的消息进行信息交换。

"__sentinel_:hello"频道:不同哨兵通过它来相护发现实现互相通信。

例子:哨兵将自己的IP(172.16.19.3)和端口(26579)发布到"__sentinel__:hello"频道上,哨兵订阅了该频道。此时哨兵2和3就可以从这个频道直接获取哨兵1的IP地址和端口号。

哨兵2,3可以和哨兵1建立网络连接。类似的,哨兵2和3之间也可以建立网络连接。这样哨兵集群就形成了。它们互相间可以通过网络连接进行通信,对主库有没有下线这事儿进行判断和协商。

      哨兵除了彼此之间建立起连接形成集群外,还需要和从库建立连接。哨兵的监控任务需要对主从库进行心跳判断,选主和通知

哨兵是如何知道从库的 IP 地址和端口的呢?

       哨兵向主库发送 INFO命令完成。哨兵2给主库发送INFO命令,主库接受这个命令以后,把从库列表返回给哨兵。哨兵根据从库列表中连接信息,和每个从库建立连接,并在这个连接上持续的对从库进行监控哨兵1和3可以通过相同方法和从库建立连接。

  

       通过pub/sub机制,哨兵之前可以组成集群,同时,哨兵又通过INFO命令,获得从库连接信息。也能和从库建立连接,并进行监控。

基于pub/sub机制的客户端事件通知

        哨兵就是一个运行在特定模式下的Redis实例,只不过并不服务请求操作,只是完成监控选主通知的任务。因此每个哨兵实例都提供pub/sub机制。客户端可以从哨兵订阅消息。哨兵提供的消息订阅频道很多,不同频道包含了主从库切换过程中的不同关键事件。

事件相关频道
主库下线事件+sdown(实例进入主观下线状态)
-sdown(实例退出主观下线状态)
+odown(实例进入客观下线状态)
-odown(实例退出客观下线状态)
从库重新配置事件+slave -reconf -sent(哨兵发送salveof命令重新配置从库)
+slave -reconf -inprog(从库配置了新主库但尚未进行同步)
+slave -reconf -done(从库配置了新主库且和新主库完成同步)
新主库切换+switch -master(主库地址发生了变化)

客户端读取哨兵配置文件,获取哨兵地址和端口,和哨兵建立网络连接,然后我们在客户端执行订阅命令,来获取不同事件消息。

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

    确定由哪个哨兵执行主从切换的过程,和主库"客观下线"的判断过程类似,也是一个"投票仲裁"的过程。

   判断客观下线的过程:多数哨兵认定该主库已经"主观下线"。

   任何一个哨兵只要自身判断主库"主观下线"后,都会给其他实例发送is-master-down-by-addr命令。接着,其他实例会根据自己和主库的连接情况做出Y或N的响应,Y相当于赞成票,N相当于反对票。

    一个哨兵获得仲裁所需的赞成票后,就可以标记主库为"客观下线",这个赞成票数是 quorum 配置项设定。

     这个哨兵就会给其他哨兵发送命令,表明希望自己来执行主从切换,并让所有其他哨兵进行投票,这个投票过程被称为"Leader选举"。因为最终执行主从切换的哨兵成为Leader,投票过程称为确定Leader

Leader 选举   

  1. 拿到半数以上的赞成票
  2. 拿到的票数同时还需要大于等于哨兵配置文件中的quorum值

以3个哨兵为例,假设此时的quorum设为2,那么任何一个想成为Leader的哨兵主要拿到2张赞成票就可以了。

时间哨兵1 s1哨兵2 s2哨兵3 s3
T1给自己投一票Y,向s2,s3发投票请求表示要成为Leader
T2给自己投一票Y,向s1,s2发投票请求表示要成为Leader
T3收到s3的请求回复N收到s3的请求回复Y
T4收到s1的请求回复N
T51票Y,1票N2票Y,成为Leader

  1. T1时刻,s1判断主库为"客观下线",他想成为Leader,给自己投一票Y,向s2,s3发投票请求表示要成为Leader。
  2. T2时刻,s3判断主库为"客观下线",他也想成为Leader,给自己投一票Y,向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。 
  5. 发生这种情况是因为s3的请求先到达,可能s1与s2之间的网络传输正好拥塞,导致投票请求传输慢了。
  6. T5时刻,s1获得1票Y,1票N,s3获得2票Y也达到预设的 quorum 值(quorum 为 2),成为Leader。
  7. 如果本轮投票没有产生leader。哨兵集群会等待一段时间(哨兵故障转移超时时间的两倍),在重新进行选举。

          哨兵集群能够进行成功投票很大程度上依赖于选举命令的正常网络传播。如果网络压力较大或者有短时间堵塞,就可能导致没有一个哨兵能够拿到半数以上的赞成票。所以等到网络拥塞好转以后成功概况会增加。如果哨兵集群只有2个实例,此时一个哨兵想要成为Leader,必须获得2票,而不是1票。如果其中1个哨兵挂掉就无法完成主从切换。

        为了实现主从切换,我们引入了哨兵;为了避免单个哨兵故障后无法进行主从切换,以及为了减少误判率,又引入了哨兵集群;哨兵集群又需要有一些机制来支撑它的正常运行。

        要保证所有哨兵实例的配置是一致的,尤其是主观下线的判断值 down-after-milliseconds。我们曾经就踩过一个“坑”。当时,在我们的项目中,因为这个值在不同的哨兵实例上配置不一致,导致哨兵集群一直没有对有故障的主库形成共识,也就没有及时切换主库,最终的结果就是集群服务不稳定。所以,你一定不要忽略这条看似简单的经验。

课后问题

    假设有一个Redis集群是"一主四从",同时配置包含了5个哨兵实例的集群,quorum值为2,那么在运行过程中,如果3个哨兵实例发生故障,此时Redis主从如果有故障,还能正确判断主库"客观下线"嘛?还能进行主从库切换嘛?是不是哨兵实例越多越好?如果调大 down-after-milliseconds 值,能否减少误判?

  1. 可以判断客观下线,因为quorum=2,当一个哨兵判断主库"主观下线"后,询问另一个哨兵,当2个哨兵都判定"主观下线",满足quorum值,因此主库"客观下线"。
  2. 不能完成客观下线,必须达到半数以上才能选出leader。
  3. 哨兵在判断"主观下线"和选举"哨兵领导者"的时候都需要和其他节点进行通信,交换信息。哨兵实例越多,通信次数也就越多,部署越多哨兵在不同机器上,节点越多带来的机器故障风险越大,这些都会影响到哨兵的通信和选举。出问题时候也会意味着选举时间变长,切换主从的时间变长。
  4. 适当调大down-after-milliseconds值,当哨兵与主库之间网络存在短时波动时,可以降低误判的概率。但是调大down-after-milliseconds值也意味着主从切换的时间会变长,对业务的影响时间越久,我们需要根据实际场景进行权衡,设置合理的阈值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值