前言
Redis sentinel设计初衷是保证Redis服务集群的稳定可用服务。其核心逻辑: 假设有Redis实例采用主从备份机制,如果master机器由于一些原因挂掉不可访问,sentinel可以自动识别出来,并且从master的slaves中选择出一个promote为master,从而保证服务可用。详细文档,参见官网。
Failover判定流程
一次failover发生的过程大致如下:
1. sentinel集群(数量为N)中某个实例S
发现某个masterM
不可访问,则S
将M
标记为sdown(subjectively down)
主观下线状态。
2. 当sentinel集群通过交谈(gossip)后,至少有quorum个sentinel认为M
不可访问后,将M
标记为odown(objectively down)
客观下线状态。
3. 处于odown
状态后,集群每个sentinel实例投票选举leader主导尝试发起failover流程。
4. 当某个leader得票数超过N/2+1(占多数)时,正式开始failover流程。
备注: 过程3、4官网文档统称为authorize(这个authorize太误导人了,下面详细说)。
源码探究
sentinel是以sentinel模式运行的redis-server。Server.c调用流程如下:
[Server.c]main() ---> initServer() ---> 调用aeCreateTimeEvent注册回调Servercron() ---> 检查sentinel_mode, 调用setSentinelTimer()
Sentinel.c中的涉及到failover判定的主要流程如下:
[Sentinel.c]setSentinelTimer() ---> sentinelHandleDictOfRedisInstances(masters) ---> sentinelHandleRedisInstance()
在sentinelHandlerRedisInstance()
中:
1. checkSubjectivelyDown()
1. checkOjbectivelyDown()
2. ifNeededFailover()
3. 进入failoverStateMechine
4. askMasterStateToOtherSentinels()
每个sentinel实例都本地维护了一张redisInstance
的字典,包括masters、masters->slaves、masters->sentinels
,gossip过程中逐步保证字典信息一致性。 例如上述的askMasteStateToOtherSentinels(),从其他sentinel获取master的state,并更新自己的dict。
checkSubjectivelyDown()
checkOjbectivelyDown()
这个函数遍历master->sentinels
字典, 统计sdown
次数,如果>=quorum(这个在配置文件里设置).则置为odown
状态。
ifNeededFailover()
首先判断满足以下情况时才进行startFailover()
过程
1. master处于odown
状态
2. 目前master没有正在进行的failover, 即master状态不处于SRI_FAILOVER_IN_PROGRESS
3. 最近没有进行failover, 最近指master->failover_timeout*2, 其中, failover_timeout是从配置文件里面读取的
startfailover()
设置master的flag=SRT_FAILOVER_IN_PROGRESS
, 获得新epoch, 设置failover_state=SENTINEL_FAILOVER_STATE_WAIT_START
后续, 进入状态机, 总共有5个状态。
SENTINEL_FAILOVER_STATE_WAIT_START
SENTINEL_FAILOVER_STATE_SELECT_SLAVE
SENTINEL_FAILOVER_STATE_SLAVEOF_NOONE
SENTINEL_FAILOVER_STATE_WATI_PROMOTION
SENTINEL_FAILOVER_STATE_RECONF_SLAVES
本文只分析failover判定过程, 即WAIT_START
到SELECT_SLAVE
的过程, 调用sentinelFailoverWaitStart()
, 主要逻辑:
1. sentinelGetLeader()
2. 如果leader不是自己, abortFailover
3. 设置为SELECT_SLAVE
getLeader()函数中,统计票数最多的一个sentinel。判断满足以下两个条件时, 返回作为leader。
1. 票数>=配置文件里的quorum
2. 票数>=sentinel总数/2 + 1
至此,正式进入failover流程。