我们学习了哨兵机制,其实现了主从库的自动切换,通过部署多个哨兵实例,从而形成一个哨兵集群,多个实例共同判断,从而实现客观的下线判断
那么哨兵内部如果有实例出现了故障导致挂掉了,其他的哨兵还能协作完成主从库的判断吗?我们先大胆的假设其工作可以正常运行,并按照这个思路考究其运行原理
在搭建哨兵集群的时候,一般只需要设置主库的IP和端口,并不会设置集群内其他哨兵的机制
sentinel monitor <master-name> <ip> <redis-port> <quorum> |
那么哨兵彼此不知道对方,如何组成的集群的?必然是通过主库作为中间件建立了链接
这就是Reids提供的pub/sub机制,也就是发布/订阅机制,哨兵只要和主库建立了链接,就可以在主库上发布消息,比如在主库上发布自己的链接信息,同时可以订阅自己的信息,就如同MQ一样,根据topic订阅,从而获取到其他哨兵实例的信息,这样就可以知道彼此的IP和端口,主库上就是有个名为 __sentinel__:hello 的topic,不同的哨兵就是通过它来互相发现的
说完了哨兵之间如何组成集群的,还需要考虑一下,哨兵如何链接上从库的呢?
从Reids的实现上来说,是利用了哨兵向主库发送INFO命令来完成的,哨兵2给主库发送INFO命令,主库接受到这个命令后,就会将从库的列表返回个主库,哨兵根据从库列表中的链接信息,和每一个从库建立了解,从而持续性的进行监控
通过pub/sub机制,哨兵之间建立了集群
通过INFO命令,获取了从库信息
之后下一个问题,就是客户端如何在切换主库之后,如何知道新主库的链接信息,才能像新主库发送请求操作,所以哨兵还需要将这个新主库的信息告诉客户端
而且客户端如何在主从切换过程获取到发生的各种事件呢?
估计还是利用的现成的方式 pub/sub机制
毕竟一个哨兵是一个类似Reids实例的进程,不过并不请求操作,只是完成监控 选主 通知的任务,诶个哨兵实例也提供pub/sub机制,客户端可以从哨兵订阅消息,利用不同的topic来获取不同的事件
常见topic如下
具体的操作如下,就是客户端和哨兵建立链接,执行对应的订阅命令,获取到不同的事件消息
SUBSCRIBE _+odown
这样在切换的时候,就可以获取到新主库的链接信息,可以监控到主从库切换过程中发生的各个重要事件,客户端就会知道主从切换到哪一步了
最后一个问题,在客观下线判断完成后,如何确定由哪个哨兵来进行实际的切换呢?
如何需要判断客观下线,需要有一定数量的哨兵都认为主库已经主观下线了
任何一个实例只要判断主库主观下线后,都会给其他实例发送下线判断命令,然后其他的实例都会根据自身情况,做出同意或者反对的响应
假设有5个哨兵,配置的quorum是3,那么客观下线需要3张票
自己判断下线后,给其他的哨兵发送命令,确定下线,确定这次下线主从切换的发起者
只要拿到的票数大于一般且符合quorum的要求,那么就可以成为主从切换的Leader了
即,T1时刻,S1判断主库客观下线,发起下线流程,希望明确自己成为主从切换的Leader
T2时刻,S3也发起了这个流程
T3时刻,S1收到了S3的投票请求,S1已经投给自己一票了,所以不会在投票,S2则将票投给了S3
T4时刻,S2拒绝投给S1,因为已经没有票了
T5时刻,S3成为了Leader,开始执行选主操作了
这就是整体切换的流程,根据此,我们发现一个哨兵要想成为Leader,至少需要2票,这样如果一个哨兵集群小于3个,那么就无法进行主从库切换了
最后总结一下:
包含pub/sub机制的哨兵集群组成过程
INFO命令获取从库列表
基于哨兵自身的pub/sub功能,完成客户端和哨兵之间的事件通知
最后是哨兵发起主从切换的流程
在此过程中,我们需要保证哨兵实例的配置是一致的,比如一个核心参数 down-after-milliseconds,要保证一致,不然可能导致无法达成共识
一个问题,一个哨兵实例的集群有5个,quorum的值为2,如果有3个哨兵实例发生了故障,还能主从切换呢?如果调大down-after-milliseconds值,是不是会减少误判呢?
不能做到主从切换,因为必须要拿到一个多数的选票
然后如果调大down-after-milliseconds的值,可以减低误判,但是会加大真正出现下线时候的主从切换时间,影响业务