24 | 从哨兵Leader选举学习Raft协议实现(下)
蒋德钧
你好,我是蒋德钧。
上节课,我给你介绍了 Raft 协议的基本流程,以及哨兵实例工作的基本过程。哨兵是通过 serverCron 函数的周期性执行,进而在 serverCron 中调用 sentinelTimer 函数,实现周期性处理哨兵相关的时间事件。而 sentinelTimer 函数处理的时间事件,就包括了对哨兵监听的每个主节点,它会通过调用 sentinelHandleRedisInstance 函数,来检查主节点的在线状态,并在主节点客观下线时进行故障切换。
另外,我还带你了解了 sentinelHandleRedisInstance 函数执行过程的前三步操作,分别是重连断连的实例、周期性给实例发送检测命令,检测实例是否主观下线,这也分别对应了 sentinelReconnectInstance、sentinelSendPeriodicCommands 和 sentinelCheckSubjectivelyDown 这三个函数,你可以再回顾下。
那么,今天这节课,我接着来给你介绍 sentinelHandleRedisInstance 函数执行过程中的剩余操作,分别是检测主节点是否客观下线、判断是否需要执行故障切换,以及需要故障切换时的哨兵 Leader 选举的具体过程。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文深入探讨了Raft协议的实现过程和哨兵Leader选举的具体实现。重点介绍了sentinelVoteLeader函数的投票逻辑,以及哨兵之间的交互询问和Leader选举过程。文章通过代码实现层面,深入浅出地解释了这些过程的具体实现逻辑,让读者能够深入了解Raft协议实现和Leader选举过程。此外,还讨论了哨兵选举的触发条件和sentinelAskMasterStateToOtherSentinels函数的另一个作用,即发起Leader选举。整体而言,本文为读者提供了深入了解Raft协议实现和Leader选举的机会。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Redis 源码剖析与实战》,新⼈⾸单¥59
《Redis 源码剖析与实战》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(6)
- 最新
- 精选
- Kaito1、一个哨兵检测判定主库故障,这个过程是「主观下线」,另外这个哨兵还会向其它哨兵询问(发送 sentinel is-master-down-by-addr 命令),多个哨兵都检测主库故障,数量达到配置的 quorum 值,则判定为「客观下线」 2、首先判定为客观下线的哨兵,会发起选举,让其它哨兵给自己投票成为「领导者」,成为领导者的条件是,拿到超过「半数」的确认票 + 超过预设的 quorum 阈值的赞成票 3、投票过程中会比较哨兵和主库的「纪元」(主库纪元 < 发起投票哨兵的纪元 + 发起投票哨兵的纪元 > 其它哨兵的纪元),保证一轮投票中一个哨兵只能投一次票 课后题:哨兵在 sentinelTimer 函数中调用 sentinelHandleDictOfRedisInstances 函数,对每个主节点都执行 sentinelHandleRedisInstance 函数,并且还会对主节点的所有从节点也执行 sentinelHandleRedisInstance 函数,那么,哨兵会不会判断从节点的主观下线和客观下线? sentinelHandleRedisInstance 函数逻辑如下: void sentinelHandleRedisInstance(sentinelRedisInstance *ri) { ... /* Every kind of instance */ // 判断主观下线 sentinelCheckSubjectivelyDown(ri); ... /* Only masters */ if (ri->flags & SRI_MASTER) { // 判断客观下线 sentinelCheckObjectivelyDown(ri); if (sentinelStartFailoverIfNeeded(ri)) sentinelAskMasterStateToOtherSentinels(ri,SENTINEL_ASK_FORCED); sentinelFailoverStateMachine(ri); sentinelAskMasterStateToOtherSentinels(ri,SENTINEL_NO_FLAGS); } } 可以看到,无论主库还是从库,哨兵都判断了「主观下线」,但只有主库才判断「客观下线」和「故障切换」。2021-09-28111
- 曾轼麟首先回到老师的问题:哨兵会判断从节点的主观下线和客观下线吗? 答:根据代码,我认为只会判断主观下线,并且在当前实例中,主观下线的slave实例是不能被选举的。 1、首先我们会发现在sentinelHandleDictOfRedisInstances函数中是存在递归调用的,当发现传入的instances是master的时候会继续对其slaves和sentinels进行递归调用,代码如下: if (ri->flags & SRI_MASTER) { //对哨兵和slaves都进行判断 sentinelHandleDictOfRedisInstances(ri->slaves); sentinelHandleDictOfRedisInstances(ri->sentinels); if (ri->failover_state == SENTINEL_FAILOVER_STATE_UPDATE_CONFIG) { switch_to_promoted = ri; } } 2、但是在调用sentinelHandleRedisInstance中的时候,只有msater才会进行【客观下线】判断,而其他实例只会进行【主观下线】判断 调用路径如下: master实例: sentinelHandleRedisInstance -> sentinelCheckSubjectivelyDown -> sentinelCheckObjectivelyDown 其它实例: sentinelHandleRedisInstance -> sentinelCheckSubjectivelyDown 在sentinelHandleRedisInstance中判断【客观下线】的代码如下所示: /* Only masters 只有master才执行 */ if (ri->flags & SRI_MASTER) { //判断客观下线 sentinelCheckObjectivelyDown(ri); if (sentinelStartFailoverIfNeeded(ri)) sentinelAskMasterStateToOtherSentinels(ri,SENTINEL_ASK_FORCED); //调用状态机方法 sentinelFailoverStateMachine(ri); sentinelAskMasterStateToOtherSentinels(ri,SENTINEL_NO_FLAGS); } 3、已经被标记了主观下线的slave,在执行sentinelSelectSlave的时候会直接跳过,我理解是在当前投票实例的角度,如果某个slave是主观下线的,它在该实例的投票是不能参选的,当前所处的状态机状态是 SENTINEL_FAILOVER_STATE_SELECT_SLAVE。 代码如下: while((de = dictNext(di)) != NULL) { sentinelRedisInstance *slave = dictGetVal(de); mstime_t info_validity_time; //被标记主观下线或者客观下线的直接跳过 if (slave->flags & (SRI_S_DOWN|SRI_O_DOWN)) continue; ........... instance[instances++] = slave; } ...... if (instances) { //先按照优先级排序 //如果优先级一样再按照 slave_repl_offset 来进行排序(选延迟最小的) qsort(instance,instances,sizeof(sentinelRedisInstance*), compareSlavesForPromotion); selected = instance[0]; }2021-09-296
- Jian硬是对了代码看了3遍才看懂:)2022-03-251
- 木这里有一个很奇怪的问题,选举主节点的时候怎么能够设置2倍的配置时间呢,如果在2倍的配置时间还没有完全主从切换,又会怎么样呢2023-05-30归属地:广东
- e⃰v⃰a⃰n⃰我想问假如master宕机了,直接在其他的从节点中随机一个做为主节点不就行了吗?为啥还要选举?选举也是随机啊!2022-05-202
- Benson_Geekmaster 记录的 Leader 的纪元(master->leader_epoch) 求问这个到底是什么东西。。。。。。。。。。。。。。。。。。。。。。。。。救命2021-12-253
收起评论