关闭

Redis Sentinel Failover判定 源码探寻

标签: sentinelfailover
207人阅读 评论(0) 收藏 举报
分类:

前言

Redis sentinel设计初衷是保证Redis服务集群的稳定可用服务。其核心逻辑: 假设有Redis实例采用主从备份机制,如果master机器由于一些原因挂掉不可访问,sentinel可以自动识别出来,并且从master的slaves中选择出一个promote为master,从而保证服务可用。详细文档,参见官网

Failover判定流程

一次failover发生的过程大致如下:
1. sentinel集群(数量为N)中某个实例S发现某个masterM不可访问,则SM标记为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_STARTSELECT_SLAVE的过程, 调用sentinelFailoverWaitStart(), 主要逻辑:
1. sentinelGetLeader()
2. 如果leader不是自己, abortFailover
3. 设置为SELECT_SLAVE

getLeader()函数中,统计票数最多的一个sentinel。判断满足以下两个条件时, 返回作为leader。
1. 票数>=配置文件里的quorum
2. 票数>=sentinel总数/2 + 1

至此,正式进入failover流程。


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:7731次
    • 积分:236
    • 等级:
    • 排名:千里之外
    • 原创:16篇
    • 转载:3篇
    • 译文:0篇
    • 评论:0条
    文章分类