上一篇中,介绍了哨兵机制可以减少主库实例下线的误判率,但是如果只有一个哨兵实例,出现宕机后没有办法保证服务的高可用,所以一般实际的生产环境都是搭建3个哨兵实例构建的集群进行运行。但是具体的运行机制是什么。其实主要就是三个问题。
- 哨兵集群之间如何进行构建连接的
- 哨兵集群如何和从库进行建立连接
- 客户端如何知道主从切换了,也就是客户端如何和哨兵集群建立连接。
pub/sub机制的哨兵集群模式
其实哨兵之间建立连接,要归功于Redis的pub/sub模式,也就是发布/订阅模式。
这个其实就是简易版的生产者消费者模式,哨兵可以在主库上进行发送和订阅具体的频道,将自己的连接信息(ip+port)发布到频道上,其他的哨兵可以通过订阅频道的事件和集群内的哨兵建立连接,具体形式即使以不同的频道进行区分。
主从集群中,有一个"sentinel:hello"的频道,不同的哨兵可以通过它来互相发现和建立连接。
如上图所示,哨兵1将自己的信息发布到"sentinel_hello"频道,具体就是172.16.19.3 以及对应的端口26579。而哨兵2和哨兵3订阅这个频道就可以获取到哨兵1的连接信息,由此就可以建立连接。这个时候就可以构建起一个哨兵集群。注意在哨兵选举主库的过程中,哨兵还需要和主从库内的从库建立连接。
哨兵集群如何和从库建立连接?
因为本身主库上存储的就有从库的info信息,只需要哨兵发送info信息就可以获取到哨兵从库的列表。哨兵就可以和从库实例构建连接。但是选举的过程中选举出一个新的主库,还需要通知给客户端新的主库实例。
pub/sub机制的客户端事件通知
哨兵就是一个特殊的服务实例,并不处理服务请求,只是负责监控、选主、和通知的任务。所以每个哨兵也提供pub/sub的机制,客户端可以从哨兵订阅消息。
主要的哨兵频道就是如下,客户端就可以通过订阅不同的频道,当客户端订阅到有+switch-naster主库地址发生变化时,就会获取到对应的新的主库实例地址。
那个哨兵执行主从切换
但是在具体的哨兵切换主库的过程中,因为哨兵集群中有多个实例,应该哪一个进行做主从切换的过程。其实这个过程有点类似于客户下线的流程,也就是需要由半数以上的实例认为哨兵应该当选leader,才可以成为leader,进行主从切换的过程。
比如集群中有三个哨兵实例构建的集群,在T1时刻,S1给自己投一篇YES,然后等待S2和S3的投票,而在S2时刻,S3给自己投了一票YES,就不能给S1投票。T3时刻,S3因为给自己投递了一票,所以回复S3为N,但是因为网络问题,S3的请求先到达S2,S2给了S3一票,而在T4时刻,S2已经投递了一票,所以给了S1N。最终的结果就是S1 1票YES,一票N。而S3是2票YES 所以S3就成为Leader。所以一般我们在生产环境中,都是构建奇数哨兵集群,主要是为了好方便选举。
总结
其实在计算机领域中,都是在一个新问题下,引入新的方案,而这个方案又带来新的问题。比如在Redis中,我们使用了复制模式,由此引入了主从模式,但是主从模式的为了实现选主的降低误判率,引入了哨兵模式,单点的哨兵模式会出现单点故障问题,所以引入了哨兵集群。