Redis哨兵模式
为什么要有哨兵机制
在Redis主从架构中,数据是读写分离的,如果主节点挂了,那么将没有主节点来服务客户端的写操作请求,也没有主节点给从节点同步数据了。
这时如果要恢复服务的话,需要人工介入,选择一个从节点成为新的主节点,然后告诉其他从节点新的主节点,同时还要通知客服端新的主节点ip地址。
这显然很不方便,如是Redis在2.8版本以后提供了哨兵(Sentinel)机制,它的作用是实现主从节点故障转移。
哨兵节点主要负责:监控、选主、通知。
如何判断主节点真的故障了
哨兵机制是通过心跳机制来判断主节点是否正常运行。通常某个哨兵在超过规定时间没有收到心跳,就会将主节点标注为主观下线。
上面判断有一个较大的问题,有可能主节点并没有故障,可能是当时系统压力比较大或者网络有堵塞,导致主节点没有在规定时间内响应给哨兵心跳。
所以,为了减少误判,通常由用多个节点部署成哨兵集群**(最少需要三台机器来部署哨兵集群)**,通过多个节点一起判断,就可以避免单个哨兵因为网络状况、主节点系统压力而造成的误判情况。
以三个哨兵集群和一主两从的Redis主从复制为例:
在一个哨兵判断主节点主观下线后,会通知其他哨兵节点进行判断,其他哨兵节点收到命令后,会根据自身与主节点心跳情况投出赞成或拒绝的票来响应。当这个哨兵集群赞成的票数达到哨兵配置文件中的quorum配置项后,主节点才会被该提出主节点下线的哨兵节点标记为客观下线。
通常quorum的值一般设置为哨兵个数的二分之一加1,例如3个哨兵就设置为2。
如何选新主节点
有那么多从节点,我们该选择哪个从节点作为新的主节点呢?
首先想到的是随机的方式,随机方式实现简单, 但是如果选到一个网络不好的从节点作为主节点,那么可能在不久将来又要来一遍主从故障迁移。
所以,我们首先要把已经下线的从节点给过滤掉,然后把之前网络状况不好的从节点也过滤掉。
那么怎么判断从节点之前网络状态不好呢?
redis有个叫down-after-milliseconds * 10 配置项,表示主从节点断连的最大连接超时时间。如果发生断连的次数超过10次,就说这个节点网络状况不好,不适合参与新的主节点选举。
把已经下线的从节点和网络状态不好的节点过滤掉后,接下来要对从节点进行三轮考察:优先级、复制进度、ID号。
- 第一轮考察:哨兵首先会根据从节点的优先级来进行排序,优先级越小排名越靠前;
- 第二轮考察:如果优先级相同,则查看复制的下标,哪个从主从复制接收的数据多,哪个就靠前;
- 第三轮考察:如果优先级和下标都相同,就选择从节点ID较小的那个。
由哪个哨兵进行主从故障转移
在选定了即将作为主节点的从节点后,由哨兵集群中哪个节点进行故障转移呢?
所以这时候,还需要在哨兵集群中选出一个leader,让leader来执行主从切换。
选举leader是一个投票的过程,那么这个投票的候选者是怎么确定的呢?
前面说到第一个提出主节点客观下线的哨兵节点,这个节点就是候选者,当选举新的主节点过程之后,候选者就会向其他哨兵发送命令,表明自己希望成为leader来执行主从切换,并让其他哨兵对它进行投票。
同样只有票数大于等于quorum的值,才会选举成功。所以quorum建议设置为哨兵个数的二分之一加1,而且哨兵的数量最少个数为3,且应该是奇数。
如何通知客服端新主节点信息
经过前面一系列的操作后,哨兵集群终于完成了主从故障迁移,那么新主节点的信息要如何通知给客服端呢?
这主要通过Redis的发布/订阅机制来实现的。每个哨兵提供发布订阅机制,客服端可以从哨兵订阅消息。
哨兵集群是如何组成的
搭建哨兵集群,只需要下面几个配置参数:
sentinel monitor <master-name> <ip> <redis-port> <quorum>
不需要其他哨兵节点的信息,其实哨兵之间是通过Redis的发布/订阅机制来相互发现的。
在配置一个哨兵后,哨兵会把自己的信息发送到sentinel:hello频道上,其他哨兵订阅了该频道,那么此时其他哨兵就可以知道该哨兵的信息,从而可以和他建立连接。
那么哨兵又是如何知道从节点的信息呢?
主节点知道所有从节点的信息,所以哨兵会向主节点发送INFO命令来获取所有从节点的信息。