Etcd Raft算法学习笔记

Raft是一种分布式一致性算法,相比于Paxos,它更容易理解和实现,效率也相当。Raft 将一致性的关键元素分成几部分,如leader选举、日志复制和安全性,实现了这几部分也就实现了一致性。

基础概念

  1. 角色: 一个Raft集群由若干个节点组成,每个节点有三种角色:leader、follower、candidate

    • leader:表示主节点,由选举产生,在选举中获得超过集群节点数量一半选票的cadidate会成为leader。leader会定期向集群的其他节点发送心跳,以维持自己的leader地位。在处理客户端请求时,必须由leader进行处理(即使follower收到请求也要转发由leader处理),它会将日志数据同步给其他follower节点,并提交给状态机执行。
    • follower:普通的从节点,follower不会主动向leader发请求,只会被动地接收来自leader的请求。在选举时会响应candidate的投票请求。
    • candidate:只有在选举阶段存在,当follower一段时间收不到来自leader的心跳,就会发起选举,成为candidate。candidate会投票给自己,并请求其他节点投票给自己。
  2. 任期
    任期是raft中的一个重要概念,它是时间轴上不重叠的一段段时间,每次发生选举时,就会进入新的任期。每个任期都有一个任期号,它是单调递增的。在选举、日志复制、安全性等问题的解决中会非常依赖这个任期号。


    任期

选举

  1. 正常情况下,一个集群中有一个leader,其他节点都是follower,leader定期向follower发送心跳,节点的角色也一直能维持,任期一直保持。
  2. 但特殊情况下,一个follower超时没有收到leader心跳,它会认为leader挂了,就会增加自己的任期号,然后向其他节点发起选举,表示竞选下一个任期的leader。此时它会遇到几种情况:
    2.1 如果它获得超过集群节点数量一半选票,它就会成为新任期的leader,并开始向其他节点发送心跳(为什么要超过一半,是为了保证在任何一个任期里都不可能产生超过一个leader。此外结合日志的提交,还能保证安全性,这个后面再说)
    2.2 如果选举超时它还没有获得超过一半的选票,它会结束这个任期的选举,成为下一个任期的candidate
    2.3 如果它收到其他candidate的选举请求:其他candidate选举的任期号比它所竞选的任期号大,它就会放弃选举,回退到follower角色;其他candidate选举的任期号小于等于它所竞选的任期号,则拒绝请求
    2.4 如果它收到leader的心跳:如果这个leader的任期号大于等于它所竞选的任期号,它就会放弃选举,回退到follower角色;如果这个leader的任期号小于它所竞选的任期号,则拒绝请求
  3. leader只有在收到比自己任期号更大的leader发来的心跳时,才退位让贤,回退到follower角色

以上2.1是期望的情况,这样可以快速选出leader。2.4发生在其他节点赢得选举的情况。而2.2和2.3发生在超过一个节点成为candidate从而导致选票被瓜分的情况,这种情况我们希望它尽量不发生,因此有一个简单的解决方法,就是每个节点的超时时间不是常数而是一定范围的随机数。这样,follower在接收心跳时的超时有先后,就会有的节点率先成为candidate;即使发生了选票瓜分,也有candidate节点会率先选举超时从而进入新任期选举,把其他candidate挤掉,这样就可以尽量避免长时间选不出leader的情况。

角色的转变关系如下图所示


三种角色的关系与转变

日志复制

Raft算法是为了保证节点内部状态的最终一致性,每个节点内部都有一个状态机,而外部客户端的请求可以被看作是一系列的日志,每个节点的状态机只要执行相同的日志序列,最终就能达到一致的状态。所以状态一致性问题就转化为了日志的一致性问题。Raft算法是依赖leader来实现日志一致性同步的。

可以看到日志包含的数据类似下图:


日志复制

日志包含一个单调递增的序列号(log index)以及当前任期的任期号(term index)
每一条日志都是由某个任期的leader产生的,然后同步给follower。如果leader中有日志与follower不一致,leader会覆盖follower的日志,确保一致性。

因此它们必然有以下性质:

  1. 如果两个节点中的两条日志,序列号和任期号一致,那么它们必然属于同一条日志,内容必然一致
  2. 如果两个节点中的两条日志,序列号和任期号一致,那么它们之前的日志的顺序和内容也必然一致

性质1没有问题,性质2是因为leader在同步日志给follower的时候,必须找到相同的一条日志,然后再按顺序把之后的日志一一复制过去,由此可以保证日志都是完全一致的

例子:
正常情况下,leader不断产生日志,不断同步给follower,不会出现不一致的情况。
但是特殊情况下,比如网络问题,集群会反复进行选举,短期内产生多个任期,如下图所示

例子

此时的leader获得了任期8,需要再log index=11的地方写入一条数据,然后将它同步给followers。对于任意一个follower,leader会从log index=11的地方开始向前尝试,直到找到一条与自己log index和term index都一致的日志,然后强制将follower这个位置之后的日志都删除,把自己这个位置之后的日志复制过来,从而实现覆盖。

安全性

以上的逻辑保证了日志的最终一致性,但似乎不能保证状态机执行的一致性。比如说:一个follower在一段不可用状态期间,leader提交了若干的日志条目,然后这个follower被选举为leader并且用新的日志条目覆盖这些日志条目;结果,不同的状态机可能会执行不同的指令序列。

所以问题的关键就在于日志在什么时候被提交给状态机执行,且被执行过的日志是不是一定能确保在leader的日志序列中。这两个问题的答案是

  1. 当leader成功将日志同步给超过集群节点数量一半的节点(包括自身)后,即可将该日志提交状态机执行
  2. 通过在选举中增加限定条件:如果一个节点A收到节点B的投票请求,而A中的最新日志比B的最新日志还新,那A就拒绝投票给B。从而确保leader的日志序列中必须包含所有已经被提交的日志,这样即使将该leader的日志覆盖其他节点,也不会造成某条日志已经被提交执行了,却又被其他leader的日志覆盖了的情况

此处“新”的定义:如果任期号不一致,则任期号大的新;如果任期号一致,则日志序列号大的新。

下面用一个例子来解释,为什么这样就能保证安全性:

  1. 一开始A节点为leader,其他节点都是follower,任期号为1。客户端向A发请求写入数据index=3时,A节点同步的时候与E、D的网络中断,只同步给了B、C,此时同步数为3超过了集群半数,因此index=3的数据可以被提交状态机执行了。
1

2.此时A节点发生了重启,假设E节点首先超时,变成candidate来竞选任期号2的任期。E、D会投票给E,但是A、B、C因为他们的最新日志比E新,所以不会投票给E,所以E一定无法当选leader。


2

由此可见,一条日志如果被提交,那么它必然已经被同步给了超过一半的节点,而那些没有被同步该日志的节点,永远无法获得超过一半的选票,也就无法成为leader。换句话说,能成为leader的节点必然包含了所有被提交了的日志记录。

所以成为leader的节点用自己的日志序列去覆盖其他节点永远是安全的。

综上,Raft算法巧妙地使用选举、日志复制和安全性保证,实现了分布式系统的最终一致性。

参考:

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

推荐阅读更多精彩内容