
1.哨兵机制
主库挂了,涉及到三个问题:
(1)主库真的挂了吗
(2)该选择哪个从库作为主库
(3)怎么把主库的相关信息同步给从库和客户端呢?
因此就有了哨兵机制,哨兵机制是解决主从切换的关键,其有效的解决了主从复制模式下故障转移的上述问题
概念:哨兵其实就是运行再特殊模式下的redis进程,其主要负责的三个任务就是上述的三个问题:
2.哨兵机制的流程
其中:
- 在监控任务中,哨兵需要判断主库是否处于下线状态;
- 在选主任务中,哨兵也要决定选择哪个从库实例作为主库
2.1.监控--主观下线和客观下线
主观下线:常规时间内主从没有响应PING命令,则哨兵会将其标记为“主观下线”
客观下线:但是哨兵可能会由于网络,或主库负载较大出现误判的情形,因此这里可以引入多个哨兵组成集群(哨兵集群),同时进行判断并少数服从多数,如果有2n+1个哨兵认为主节点下线(个数可配置),则标记为“客观下线”,否则则为上线
具体实现:
任何哨兵认为主节点主观下线了,就会发送is-master-down-by-addr
命令。接着其他哨兵收到命令后检查与主库的连接状况,根据状况返回Y或N,当赞成票数目大于所配置的quorum
配置,则标记主库为客观下线。此时这个哨兵就可以进入leader选举
流程了

2.2.如何选主
流程:筛选+打分,就是将不符合要求的从库筛选掉,按照一定的规则打分选主

(1)筛选:
(2)打分
三个规则,从上到下规则进行选主,只有当某轮选不出才会进入下一轮
2.3.一些问题:
1.哨兵在操作主从切换的过程中,客户端能否正常地进行请求操作?
读请求可以,写请求会失败,失败持续的时间 = 哨兵切换主从的时间 + 客户端感知到新主库,此时可以通过消息队列的方式防止数据丢失
down-after-milliseconds参数:响应超时时间配置
2.客户端如何感知主从切换?
(1)哨兵通知
哨兵将主库的地址写入自己实例的pubsub(switch-master)实例中,客户端会订阅这个pubsub,主从切换后哨兵会将主节点的信息放入pubsub
(2)客户端主动获取
但是如果哨兵通知客户端失败了该怎么办?客户端访问从库是可通过sentinel get-master-addr-by-name拿到地址,这样不管怎么样都能拿到最新的地址。
一般Redis的SDK都提供了通过哨兵拿到实例地址,再访问实例的方式
3.哨兵集群如果挂了个节点怎么办?
哨兵集群类似zk,多数可用即可
4.由哪个哨兵执行选主(主从切换)
通过选举选出“哨兵领导者”
3.哨兵集群
3.1基于pub/sub机制的哨兵集群
哨兵集群的配置信息中只配置了主库的IP和端口:sentinel monitor <master-name> <ip> <redis-port> <quorum>
-
获取哨兵地址
就是基于pub/sub的订阅通知机制,只有订阅了同一个频道的应用,才能通过发布的消息进行信息交换。
主从集群上,有一个名为__sentinel__:hello
的频道,通过该频道,哨兵能够知道其他哨兵的地址,因此就能够互相之前通过建立连接进行通信。如下图:

-
获得从库地址
哨兵通过向主库发送INFO
命令,主库将发送从库的信息(slave列表)给哨兵,因此哨兵就能够建立与从库的连接并监控

-
客户端的主从切换推送
哨兵也是一个redis服务,因此其也提供订阅/通知机制,客户端可以从哨兵订阅频道并获得不同的消息,例如订阅+switch-master来获得主从切换的通知,从消息中拿到新的主节点的信息并建立连接。
几个关键事件如下:

3.2.哨兵Leader选举
选举时机:哨兵将主节点标记为”客观下线“后,将发起自己的选票选举为主从切换的哨兵节点
投票过程中,成为leader需要两个条件
(1)拿到半数的赞同票
(2)拿到的票数需要大于哨兵配置的quorum
值(如果没有拿到半数票,但是拿到了超过quorum
值的选票的话,还是无法成为leader节点)
选举流程如下:

其中当节点回复过Y之后,其它的选票会回复N,并且投过票后无法发起选票,节点进入判定“客观下线”的流程并得到Y就会发起选票流程。
当网络压力较大或有短时堵塞的时候,可能会产生没有节点得到半数的选票的场景,这个时候会等待哨兵故障转移超时时间的两倍的时间,再次发起选举。(哨兵的正常选举依赖网络指令的正常传播)
一个哨兵要想成为Leader,必须获得2票,而不是1票。所以,如果有个哨兵挂掉了,那么,此时的集群是无法进行主从库切换的。因此,通常我们至少会配置3个哨兵实例
哨兵集群采用的类似于Raft的共识算法(指的是集群中多个节点如何就一个问题达成共识)进行Leader选举
对于哨兵配置而言:要保证所有哨兵实例的配置是一致的,尤其是主观下线的判断值down-after-milliseconds