哨兵集群
哨兵机制的基本流程
-
在 Redis 主从集群中,哨兵机制是实现主从库自动切换的关键机制。
-
哨兵其实就是一个运行在特殊模式下的 Redis 进程,主从库实例运行的同时,它也在运行。哨兵主要负责的就是三个任务:监控、选主(选择主库)和通知。
- 监控
- 哨兵进程在运行时,周期性地给所有的主从库发送 PING 命令,检测它们是否仍然在线运行。
- 如果从库没有在规定时间内响应哨兵的 PING 命令,哨兵就会把它标记为“下线状态”。
- 同样,如果主库也没有在规定时间内响应哨兵的 PING 命令,哨兵就会判定主库下线,然后开始自动切换主库的流程。
- 选主
- 主库挂了以后,哨兵就需要从很多个从库里,按照一定的规则选择⼀个从库实例,把它作为新的主库。
- 这⼀步完成后,现在的集群里就有了新主库。
- 通知
- 在执行通知任务时,哨兵会把新主库的连接信息发给其他从库,让它们执行 replicaof 命令,和新主库建立连接,并进行数据复制。
- 同时,哨兵会把新主库的连接信息通知给客户端,让它们把请求操作发到新主库上。
- 监控
主观下线和客观下线
- 哨兵进程会使用 PING 命令检测它自己和主、从库的网络连接情况,用来判断实例的状态。
- 如果哨兵发现主库或从库对 PING 命令的响应超时了,那么,哨兵就会先把它标记为“主观下线”。
- 如果检测的是从库,那么,哨兵简单地把它标记为“主观下线”就行了,因为从库的下线影响一般不太大,集群的对外服务不会间断。
- 但是,如果检测的是主库,那么,哨兵还不能简单地把它标记为“主观下线”,开启主从切换。因为很有可能哨兵误判了,其实主库并没有故障。一旦启动了主从切换,后续的选主和通知操作都会带来额外的计算和通信开销。
- 哨兵机制通常会采用多实例组成的集群模式进行部署,这也被称为哨兵集群。
- 引入多个哨兵实例一起来判断,就可以避免单个哨兵因为自身网络状况不好,而误判主库下线的情况。
- 同时,多个哨兵的网络同时不稳定的概率较小,由它们一起做决策,误判率也能降低。
- 在判断主库是否下线时,不能由一个哨兵说了算,只有大多数的哨兵实例,都判断主库已经“主观下线”了,主库才会被标记为“客观下线”,这个叫法也是表明主库下线成为⼀个客观事实了。这个判断原则就是:少数服从多数。同时,这会进一步触发哨兵开始主从切换流程。
如何选定新主库?
- 哨兵选择新主库的过程称为“筛选+打分”。
- 简单来说,我们在多个从库中,先按照一定的筛选条件,把不符合条件的从库去掉。
- 一般情况下,我们肯定要先保证所选的从库仍然在线运行。
- 除了要检查从库的当前在线状态,还要判断它之前的网络连接状态。
- 如果从库总是和主库断连,而且断连次数超出了一定的阈值,我们就有理由相信,这个从库的网络状况并不是太好,就可以把这个从库筛掉了。
- 然后,我们再按照一定的规则,给剩下的从库逐个打分,将得分最高的从库选为新主库。
- 我们可以分别按照三个规则依次进行三轮打分,这三个规则分别是从库优先级、从库复制进度以及从库 ID号。
- 只要在某一轮中,有从库得分最高,那么它就是主库了,选主过程到此结束。
- 第一轮:优先级最高的从库得分高。
- 可以通过 slave-priority 配置项,给不同的从库设置不同优先级。
- 第二轮:和旧主库同步程度最接近的从库得分高。
- 我们想要找的从库,它的 slave_repl_offset 需要最接近 master_repl_offset。
- 如果在所有从库中,有从库的 slave_repl_offset 最接近 master_repl_offset,那么它的得分就最高,可以作为新主库。
- 第三轮:ID 号小的从库得分高。
- 在优先级和复制进度都相同的情况下,ID 号最小的从库得分最高,会被选为新主库。
- 简单来说,我们在多个从库中,先按照一定的筛选条件,把不符合条件的从库去掉。
哨兵集群:哨兵挂了,主从库还能切换吗?
- 实际上,一旦多个实例组成了哨兵集群,即使有哨兵实例出现故障挂掉了,其他哨兵还能继续协作完成主从库切换的工作,包括判定主库是不是处于下线状态,选择新主库,以及通知从库和客户端。
- 在配置哨兵的信息时,我们只需要用到
sentinel monitor <master-name> <ip> <redis-port> <quorum>
,设置主库的 IP 和端口,并没有配置其他哨兵的连接信息。
基于 pub/sub 机制的哨兵集群组成
-
哨兵实例之间可以相互发现,要归功于 Redis 提供的 pub/sub 机制,也就是发布/订阅机制。
- 哨兵只要和主库建立起了连接,就可以在主库上发布消息了,比如说发布它自己的连接信息(IP和端口)。
- 同时,它也可以从主库上订阅消息,获得其他哨兵发布的连接信息。
- 当多个哨兵实例都在主库上做了发布和订阅操作后,它们之间就能知道彼此的IP地址和端口。
-
为了区分不同应用的消息,Redis 会以频道的形式,对这些消息进行分门别类的管理。
- 所谓的频道,实际上就是消息的类别。
- 当消息类别相同时,它们就属于同一个频道。
- 只有订阅了同一个频道的应用,才能通过发布的消息进行信息交换。
-
在主从集群中,主库上有一个名为 “sentinel:hello” 的频道,不同哨兵就是通过它来相互发现,实现互相通信的。
-
哨兵除了彼此之间建立起连接形成集群外,还需要和从库建立连接。这是因为,在哨兵的监控任务中,它需要对主从库都进行心跳判断,而且在主从库切换完成后,它还需要通知从库,让它们和新主库进行同步。
- 哨兵是如何知道从库的 IP 地址和端口的呢?这是由哨兵向主库发送 INFO 命令来完成的。
- 我们仍然可以依赖 pub/sub 机制,来帮助我们完成哨兵和客户端间的信息同步。
基于 pub/sub 机制的客户端事件通知
- 客户端读取哨兵的配置文件后,可以获得哨兵的地址和端口,和哨兵建立网络连接。
- 然后,我们可以在客户端执行订阅命令,来获取不同的事件消息。
由哪个哨兵执行主从切换?
- 任何一个实例只要自身判断主库“主观下线”后,就会给其他实例发送 is-master-down-by-addr 命令。
- 接着,其他实例会根据自己和主库的连接情况,做出 Y 或 N 的响应,Y 相当于赞成票,N 相当于反对票。
- 一个哨兵获得了仲裁所需的赞成票数后,就可以标记主库为“客观下线”。
- 这个所需的赞成票数是通过哨兵配置文件中的 quorum 配置项设定的。
- 此时,这个哨兵就可以再给其他哨兵发送命令,表明希望由自己来执行主从切换,并让所有其他哨兵进行投票。
- 这个投票过程称为“Leader选举”。
- 因为最终执行主从切换的哨兵称为 Leader,投票过程就是确定 Leader。
- 在投票过程中,任何一个想成为 Leader 的哨兵,要满足两个条件:第一,拿到半数以上的赞成票;第二,拿到的票数同时还需要大于等于哨兵配置文件中的 quorum 值。