Raft系列4 任期和选举(原创)

可能是你能找到的最完整最详细的中文版的Raft算法说明博客

内容来源都是原生的论文,可以保证内容的可靠性,并且对论文里面的很多细节做了扩展说明

任期的概念 term

image

image

任期的概念:

  • Raft 把时间分割成任意长度的任期(term),如图 5 所示。任期用连续的整数标记。
  • 每一段任期从一次选举开始,一个或者多个 candidate 尝试成为 leader 。如果一个 candidate 赢得选举,然后他就在该任期剩下的时间里充当 leader 。在某些情况下,一次选举无法选出 leader 。在这种情况下,这一任期会以没有 leader 结束;一个新的任期(包含一次新的选举)会很快重新开始。
  • Raft 保证了在任意一个任期内,最多只有一个 leader

个人理解:

  • 在raft算法中,比较谁的数据最新有2个参考指标,任期和logIndex,任期大的节点,数据一定最新,任期一样的话,就要比较该任期内谁的MaxLogIndex最大了。引入任期的概念可以简化数据比较的精度。

任期的作用:

  • 不同的服务器节点观察到的任期转换的次数可能不同,在某些情况下,一个服务器节点可能没有看到 leader 选举过程或者甚至整个任期全程。

  • 任期在 Raft 算法中充当逻辑时钟的作用,这使得服务器节点可以发现一些过期的信息比如过时的 leader 。

  • 每一个服务器节点存储一个当前任期号,该编号随着时间单调递增。

  • 服务器之间通信的时候会交换当前任期号;

  • 如果一个服务器的当前任期号比其他的小,该服务器会将自己的任期号更新为较大的那个值。

  • 如果一个 candidate 或者 leader 发现自己的任期号过期了,它会立即回到 follower 状态。(所以说老leader如果发生了网络分区,后来接收到新leader的心跳的时候,比拼完任期之后,会自动变成follower。

  • 如果一个节点接收到一个包含过期的任期号的请求,它会直接拒绝这个请求。

选举的发起流程:

image
  • 每个Node启动的时候,初始化Role都是Follower,并且启动计时器,超时还没接收到消息(可以是Leader的AppendEntries RPC,也可以是 Candidate的Vote RPC)
  1. Raft集群的启动选举
    Raft 使用一种心跳机制来触发 leader 选举。当服务器程序启动时,他们都是 follower 。一个服务器节点只要能从 leader 或 candidate 处接收到有效的 RPC 就一直保持 follower 状态。Leader 周期性地向所有 follower 发送心跳(不包含日志条目的 AppendEntries RPC)来维持自己的地位。
    如果一个 follower 在一段选举超时时间内没有接收到任何消息,它就假设系统中没有可用的 leader ,然后开始进行选举以选出新的 leader。

  2. 选举过程
    要开始一次选举过程,follower 先增加自己的当前任期号并且转换到 candidate 状态。然后投票给自己并且并行地向集群中的其他服务器节点发送 RequestVote RPC(让其他服务器节点投票给它)。
    Candidate 会一直保持当前状态直到以下三件事情之一发生:
    (a) 它自己赢得了这次的选举(收到过半的投票)
    (b) 其他的服务器节点成为 leader
    (c) 一段时间之后没有任何获胜者。这些结果会在下面的章节里分别讨论。

当一个 candidate 获得集群中过半服务器节点针对同一个任期的投票,它就赢得了这次选举并成为 leader 。
对于同一个任期,每个服务器节点只会投给一个 candidate ,按照先来先服务(first-come-first-served)的原则(注意:5.4 节在投票上增加了额外的限制)。
要求获得过半投票的规则确保了最多只有一个 candidate 赢得此次选举(图 3 中的选举安全性)。
一旦 candidate 赢得选举,就立即成为 leader 。然后它会向其他的服务器节点发送心跳消息来确定自己的地位并阻止新的选举。

在等待投票期间,candidate 可能会收到另一个声称自己是 leader 的服务器节点发来的 AppendEntries RPC 。
如果这个 leader 的任期号(包含在RPC中)不小于 candidate 当前的任期号,那么 candidate 会承认该 leader 的合法地位并回到 follower 状态。
如果 RPC 中的任期号比自己的小,那么 candidate 就会拒绝这次的 RPC 并且继续保持 candidate 状态。

第三种可能的结果是 candidate 既没有赢得选举也没有输:如果有多个 follower 同时成为 candidate ,那么选票可能会被瓜分以至于没有 candidate 赢得过半的投票。
当这种情况发生时,每一个候选人都会超时,然后通过增加当前任期号来开始一轮新的选举。然而,如果没有其他机制的话,该情况可能会无限重复。

Raft 算法使用随机选举超时时间的方法来确保很少发生选票瓜分的情况,就算发生也能很快地解决。为了阻止选票一开始就被瓜分,选举超时时间是从一个固定的区间(例如 150-300 毫秒)随机选择。这样可以把服务器都分散开以至于在大多数情况下只有一个服务器会选举超时;然后该服务器赢得选举并在其他服务器超时之前发送心跳。同样的机制被用来解决选票被瓜分的情况。每个 candidate 在开始一次选举的时候会重置一个随机的选举超时时间,然后一直等待直到选举超时;这样减小了在新的选举中再次发生选票瓜分情况的可能性。9.3 节展示了该方案能够快速地选出一个 leader 。

个人理解:
选举其实看其实PK3个指标:term、LastLogIndex、lastLogTerm,至少要不比自己小才会vote给你,实际上这并不能保证最新的数据

因为vote RPC里面,只有lastLogIndex和Term,可能leader里面的lastLog是未提交的状态,但是其它follower的状态是提交的。所以新一任leader上任之前做的第一件事就是发一个心跳,update lastCommitIndex

投票消息(候选者发起)

follow在一定时间内未接收到leader发过来的heartbeat,超时后自己状态成为候选者,并且向其它的所有节点发起一个投票消息

一个完整的投票消息包括4个参数

  1. 自己的term
  2. 候选者ID(自己的ID)
  3. lastLogIndex index of candidate’s last log entry
  4. lastLogTerm term of candidate’s last log entry

receiver节点:先判断term,再判断日志是否是最新的。至少任期以及日志记录,不比自己旧,才会投票给你。所以过时的节点不会得到大多数的投票。

启动投票

  1. 系统刚刚启动,所有节点的任期都是0,大家的role都是follower
  2. 一个启动的节点第一个触发未检测到心跳超时,自增任期为1,并且重新计时(投票开始时间),给自己投一票,然后向所有的其它节点发起投票
  3. 其它节点当前的任期都为0,且日志也没空,肯定会投票给它,而且这些节点因为收到了candidate的投票选举,清零自己的心跳空白等待时间,未超时前不会发起投票,从而避免多重投票导致无效投票的可能性
  4. 第一个发起投票的节点收到半数投票,成为leader。即使投票失败(半数投票不成功)也要等到自己投票超时时间,到了超时时间之后,再自增任期,发起新的一轮投票。

运行中发起投票

  1. 每次follower收到leader的一次HeartBeat,都会清零自己的心跳计时器,重新开始计时,如果当前心跳计时器超时了,仍然未收到leader的心跳,就会从follower变成candidate
  2. 自增当前任期,且开始计时(选举计时),向其它节点发起投票
  3. 其它节点会比较 任期和日志的序号,至少不能比自己的数据旧才会投票给第一个发起投票的节点
  4. 超过半数节点投票成功,才会成为leader,否则要等待选举超时,再发起第二轮投票

投票期间重新收到leader心跳

candidate之所以会发起选举,是因为没有收到leader的心跳,但是在选举期间又重新收到心跳会如何?
论文中描述,当重新受到leader的心跳时会判断term,至少不能比自己小,也就是说,即使是因为自己网络原因没有收到心跳而发起投票,也不会终止这次投票,因为老leader的term比现在的要小,自己是自增了一次的。
但是如果在投票等待期间,已经有新的leader产生,并且接收到leader的 appending的RPC时,candidate会放弃投票,因为term不小于当前candidate,说明这个leader不是老leader,要么和自己是同一个term的leader,要么比自己更新term的leader。
所以理论上存在某一个follower的节点因为网路延迟而发起leader申请,并且还有可能成功顶替leader的可能性,即使leader的功能正常,是这个follower自己的网络突然发生了延迟。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容