首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Reids哨兵模式详解

当主库宕机了,客户端如何进行写操作?

此时就需要哨兵来帮忙,将一个从库升级为主库。

哨兵主要负责的就是三个任务:监控、选择主库和通知。

监控

监控是指哨兵进程在运行时,周期性地给所有的主从库发送 PING 命令,检测它们是否仍然在线运行。如果从库没有在规定时间内响应哨兵的 PING 命令,哨兵就会把它标记为“下线状态”;

同样,如果主库也没有在规定时间内响应哨兵的 PING 命令,哨兵就会判定主库下线,然后开始自动切换主库的流程。

下线判断分为“主观下线”和“客观下线”两种。

选择主库

主库挂了以后,哨兵就需要从很多个从库里,按照一定的规则选择一个从库实例,把它作为新的主库。

选择新主库的过程称为“筛选 + 打分”。

通知

哨兵会把新主库的连接信息发给其他从库,让它们执行 replicaof 命令,和新主库建立连接,并进行数据复制。

同时,哨兵会把新主库的连接信息通知给客户端,让它们把请求操作发到新主库上。

主观下线

哨兵进程会使用 PING 命令检测它自己和主、从库的网络连接情况,用来判断实例的状态。

如果哨兵发现从库对 PING 命令的响应超时了。由于从库的下线影响一般不太大,可直接标记为“主观下线”

主库则不可这么随便,一旦启动了主从切换,后续的选主和通知操作都会带来额外的计算和通信开销。为了避免哨兵误判(一般会发生在集群网络压力较大、网络拥塞,或者是主库本身压力较大的情况下)。

通常会采用多实例组成的集群模式进行部署,这也被称为哨兵集群。引入多个哨兵实例一起来判断,就可以避免单个哨兵因为自身网络状况不好,而误判主库下线的情况。同时,多个哨兵的网络同时不稳定的概率较小,由它们一起做决策,误判率也能降低。

客观下线

在哨兵集群的情况下,只有大多数的哨兵实例,都判断主库已经“主观下线”了,主库才会被标记为“客观下线”。判断原则就是:少数服从多数。

当有 N 个哨兵实例时,最好要有 N/2 + 1 个实例判断主库为“主观下线”,才能最终判定主库为“客观下线”。

筛选

检查从库的当前在线状态,判断它之前的网络连接状态。(down-after-milliseconds)

如果在 down-after-milliseconds 毫秒内,主从节点都没有通过网络联系上,我们就可以认为主从节点断连了。如果发生断连的次数超过了 n 次,就说明这个从库的网络状况不好,不适合作为新主库。

要保证所有哨兵实例的配置是一致的,尤其是主观下线的判断值 down-after-milliseconds。否则可能导致集群服务不稳定。

打分

1,优先级最高的从库得分高(slave-priority 配置项)

2,和旧主库同步程度最接近的从库得分高(repl_backlog_buffer:详见上篇文章)

3,ID 号小的从库得分高

哨兵见如何互相通信?

通过 pub/sub (发布/订阅)机制,哨兵只要和主库建立起了连接,每个哨兵都把自己的信息发送给主库,然后从主库订阅其他哨兵的消息,这样就可以互相知道其他哨兵的地址了。

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

这是由哨兵向主库发送 INFO 命令来完成的。就像下图所示,哨兵 2 给主库发送 INFO 命令,主库接受到这个命令后,就会把从库列表返回给哨兵。

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

主从切换后,哨兵是如何告知客户端新的主库

通过 pub/sub (发布/订阅)机制,客户端可以从哨兵订阅消息。哨兵提供的消息订阅频道有很多,不同频道包含了主从库切换过程中的不同关键事件。

主库故障以后,哨兵集群有多个实例,那怎么确定由哪个哨兵来进行实际的主从切换呢?

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

2,一个哨兵获得了仲裁所需的赞成票数后,就可以标记主库为“客观下线”。

3,此时,这个哨兵就可以再给其他哨兵发送命令,表明希望由自己来执行主从切换,并让所有其他哨兵进行投票。这个投票过程称为“Leader 选举”。

如果哨兵集群只有 2 个实例,此时,一个哨兵要想成为 Leader,必须获得 2 票,而不是 1 票。所以,如果有个哨兵挂掉了,那么,此时的集群是无法进行主从库切换的。因此,通常我们至少会配置 3 个哨兵实例。

哨兵在操作主从切换的过程中,客户端能否正常地进行请求操作?

如果客户端使用了读写分离,那么读请求可以在从库上正常执行,不会受到影响。但是由于此时主库已经挂了,而且哨兵还没有选出新的主库,所以在这期间写请求会失败,失败持续的时间 = 哨兵切换主从的时间 + 客户端感知到新主库 的时间。

如果不想让业务感知到异常,客户端只能把写失败的请求先缓存起来或写入消息队列中间件中,等哨兵切换完主从后,再把这些写请求发给新的主库,但这种场景只适合对写入请求返回值不敏感的业务,而且还需要业务层做适配,另外主从切换时间过长,也会导致客户端或消息队列中间件缓存写请求过多,切换完成之后重放这些请求的时间变长。

哨兵检测主库多久没有响应就提升从库为新的主库,这个时间是可以配置的(down-after-milliseconds参数)。配置的时间越短,哨兵越敏感,哨兵集群认为主库在短时间内连不上就会发起主从切换,这种配置很可能因为网络拥塞但主库正常而发生不必要的切换,当然,当主库真正故障时,因为切换得及时,对业务的影响最小。如果配置的时间比较长,哨兵越保守,这种情况可以减少哨兵误判的概率,但是主库故障发生时,业务写失败的时间也会比较久,缓存写请求数据量越多。

哨兵提升一个从库为新主库后,客户端因为某些原因错过了哨兵的通知怎么办?

哨兵提升一个从库为新主库后,哨兵会把新主库的地址写入自己实例的pubsub(switch-master)中。客户端需要订阅这个pubsub,当这个pubsub有数据时,客户端就能感知到主库发生变更,同时可以拿到最新的主库地址,然后把写请求写到这个新主库即可,这种机制属于哨兵主动通知客户端。

如果客户端因为某些原因错过了哨兵的通知,或者哨兵通知后客户端处理失败了,安全起见,客户端也需要支持主动去获取最新主从的地址进行访问。

所以,客户端需要访问主从库时,不能直接写死主从库的地址了,而是需要从哨兵集群中获取最新的地址(sentinel get-master-addr-by-name命令),这样当实例异常时,哨兵切换后或者客户端断开重连,都可以从哨兵集群中拿到最新的实例地址。

即为推拉结合。

redis主从切换维持数据最终一致性吗?(数据是否会丢失?)

redis不是最终一致性,leader未同步数据给flow节点时挂了发生主从切换,未同步的数据就丢失了。

而像ZooKeeper这类ZAB协议,是要Leader同步超过半数Flow节点,才告知客户的写操作成功,如果Leader挂了重新选出的Leader也有最新的数据。

哨兵实例是不是越多越好?

并不是,哨兵在判定“主观下线”和选举“哨兵领导者”时,都需要和其他节点进行通信,交换信息,哨兵实例越多,通信的次数也就越多,而且部署多个哨兵时,会分布在不同机器上,节点越多带来的机器故障风险也会越大,这些问题都会影响到哨兵的通信和选举,出问题时也就意味着选举时间会变长,切换主从的时间变久。

小总结

哨兵集群的构建主要通过pub/sub机制来组成。

哨兵集群基于INFO命令和所有从库建立连接。

哨兵和从库之间可以通过pub/sub机制完成消息的订阅和事件通知。

哨兵认定主库客观下线,需要有超过quorum值数量的哨兵认定主库为主观下线。认定了主库为客观下线的哨兵有资格开始成为领导者哨兵的候选人,并发起投票。

只有候选人才能够投自己一票,其他的哨兵(未认定主库为客观下线的)只能够投给第一个接收到的投票请求。并且只能投赞成票一次。后者都是反对票。

热爱技术才能学好技术

每天进步一点点

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20230206A06X2A00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券