跳至主要內容

哨兵集群的组成和运行

AruNi_Lu数据库Redis约 2346 字大约 8 分钟

本文内容

前言

哨兵机制:主库挂了怎么办open in new window 中简单介绍了哨兵机制,它其实是由多个哨兵实例组成的 哨兵集群,所以即使有实例出现故障,其他哨兵还能继续完成 主从库切换 的工作,包括 判定主库是否下线、选择新主库、通知从库和客户端

这篇文章就来看看,哨兵集群是如何组成、如何运行的

1. pub/sub — 哨兵集群的组成

在部署哨兵集群时,只需要使用下面这个配置,设置 主库的 IP 和端口 即可,并没有配置其他哨兵的连接信息:

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

所以哨兵之间是不知道彼此的地址的,那是如何组成哨兵集群的呢?这就要提到 Redis 的 pub/sub 机制 了,这是一种发布/订阅机制,其使得 哨兵实例之间可以相互发现

1.1 哨兵之间建立连接

哨兵和主库建立连接后,就可以 在主库上发布消息了,比如发布自己的 连接信息(IP + 端口)。同时也能 从主库上订阅消息,获得其他哨兵发布的连接信息

所以,只需要通过主库,多个哨兵实例就可以知道 彼此的连接信息

当然了,客户端也可以进行发布和订阅,为了区分不同的消息,Redis 以频道(类似于 topic)的形式,对消息进行分类管理。只有订阅了同一个频道,才能互相交换消息。

不同的哨兵是通过一个名为 __sentinel__:hello 的频道来互相发现、互相通信的。例如,有三个哨兵实例,哨兵 1 把自己的连接信息发布到主库的该频道上,哨兵 2 和 3 订阅了该频道,就可以从中获取哨兵 1 的连接信息,从而和它建立网络连接。同理,哨兵 2 和 3 也可以通过该方法建立起网络连接,这样哨兵之间就都连接起来了,哨兵集群就形成了。它们之间可以通过网络连接进行通信,完成主从库切换过程。如下图所示:

img

1.2 哨兵监控从库

不过,除了哨兵彼此之间建立连接外,还需要和从库建立连接,因为哨兵需要 对主库和从库都进行监控,而且在主从库切换完成后,还要 通知其他从库与新主库进行数据同步

那哨兵如何知道从库的 IP 和端口?这需要使用 INFO 命令。

具体来说,哨兵向主库发送 INFO 命令,主库就会返回从库列表给哨兵,然后哨兵就可以根据从库列表中的连接信息,和每个从库建立连接,监控从库的状态。如下图所示:

img

通过 pub/sub 机制,哨兵之间可以建立连接来组成集群,同时,哨兵又 通过 INFO 命令,可以获取到从库的连接信息,从而 与从库建立连接监控它们

1.3 哨兵通知客户端

主从库切换后,哨兵还需要通知客户端新主库的连接信息,那哨兵如何通知客户端呢?这任然需要依赖 pub/sub 机制。

哨兵也是一个特别的 Redis 实例,只是它不服务请求操作,只是完成监控、选主和通知。所以 每个哨兵实例也提供 pub/sub 机制,客户端可以从哨兵订阅消息,哨兵提供了很多订阅频道,如下所示:

img

具体来说,客户端需要读取哨兵的配置文件,获得哨兵的地址和端口,和哨兵建立网络连接后,就可以订阅不同的频道来获取不同的消息了

哨兵的配置一般配置在配置文件或配置中心中,所以直接读取对应的配置即可。

例如,可以通过如下命令,订阅相关信息: :

SUBSCRIBE +odown	# 订阅主库实例进入客观下线状态的事件

PSUBSCRIBE  *	# 订阅所有事件

客户端订阅了 +switch-master 频道后,当哨兵选出新主库,客户端就会看到下面的事件消息:

switch-master <master name> <oldip> <oldport> <newip> <newport>

该消息中就有新主库的连接信息,因此客户端就可以从该消息中获取新主库的地址和端口,从而进行请求了。

哨兵机制:主库挂了怎么办open in new window 中也说过,还可以通过 sentinel get-master-addr-by-name 命令,从哨兵集群中获取主从库的地址进行访问

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

哨兵机制:主库挂了怎么办open in new window 中简单提到过,哨兵集群在判断出主库 “客观下线” 后,会选出一个 “哨兵领导者”,之后的整个过程都由它来完成主从切换

下面来看看详细的过程。

哨兵集群要判定主库 “客观下线”,需要有一定数量的实例都认为主库已经 “主观下线” 了。

一个哨兵自己认为主库 “主观下线” 后,会给其他哨兵发送 is-master-down-by-addr 命令,其他哨兵收到后会根据自己和主库的连接情况,做出 Y(赞成票)或 N(反对票)响应:

img

当一个哨兵获取了一定的赞成票数后,就可以标记主库为 “客观下线” 了。这个一定的赞成票数由哨兵配置文件中的 quorum 配置项 设定。例如有 5 个哨兵,quorum 配置等于 3,那一个哨兵获取了 3 张赞成票就可以了,其中包括自己的赞成票。

注意:此时还没选出哨兵 Leader,只是把主库标记为了 “客观下线”,还有一轮投票才能选出哨兵 Leader

接着,该哨兵会给其他哨兵发送命令,表明希望由自己来执行主从切换,并让其他哨兵进行投票,其他哨兵会给首先收到命令的哨兵投赞成票。这个投票过程就是 Leader 选举

想要成为哨兵 Leader,需要满足 两个条件

  • 拿到哨兵集群数量的半数以上赞成票
  • 拿到的赞成票要大于等于配置项 quorum 的值

例如,有 5 个哨兵实例,quorum 配置等于 3,那哨兵需要拿到 3 张赞成票,才能成为哨兵 Leader。

如果在这一轮投票中 没有达到两个条件,那 这一轮就不会产生哨兵 Leader,此时会 等待一段时间(哨兵故障转移超时时间的 2 倍),再重新选举

为什么要等待一段时间?因为 在网络压力较大或短时堵塞时,就可能会导致哨兵没能获取半数以上的赞成票,所以需要等待一会,让网络恢复后再进行投票,成功率会更高

注意:如果哨兵集群只有 2 个实例,那要选举出哨兵 Leader 就必须获取 2 票,而不是 1 票。所以如果有一个哨兵挂了,该集群就无法进行主从切换了。所以一般 至少要配置 3 个哨兵实例

不过 哨兵实例也不是越多越好,毕竟哨兵在 判断主库 “客观下线” 和 “选举哨兵 Leader” 时,都需要和其他节点进行通信,哨兵实例越多,通信的次数也越多,会导致通信时间边长,主从库的切换耗时增加

3. 参考文章

  • 《Redis 核心技术与实战》
上次编辑于: