Raft协议简析

什么是Replicated state machines(复制状态机):

一致性算法之所以可以保证在有节点挂掉时也能够继续服务, 就是因为有Replicated state machines的存在。 在分布式系统中, 有两种方式来实现这个复制状态机

  1. 用一个专门节点负责记录整个集群的元信息, 如HDFS, GFS
  2. 每个节点都会记录replicated log,确保每个节点的log最终都包含了相同的请求, 并且是同样的顺序

一致性算法一般有一下特点:

  1. 保证安全(不会返回错误数据)
  2. 只有半数以上的节点存活就可以继续提供服务
  3. 不依赖时钟来提供一致性, 最多会造成不可用
  4. 通常只要半数以上节点完成请求就算成功, 小部分慢节点不会影响整个系统的性能

为啥不用Paxos?

  1. 不清晰, 难以理解
  2. 不好实现, 只提供了single-decree Paxos的细节, 没有给出multi-Paxos的细节

Raft一致性算法

Raft算法首先会选举一个leader, 然后又leader来管理replicated log。 leader会从client处接收请求, 然后转发给别的节点, 并且告诉这些节点什么时候可以把这些请求应用在状态机上(落地)。 当一个leader挂了的时候, 会马上选举出一个新的leader。 由上可知, Raft将一致性问题拆分成了3个独立的子问题:

  1. Leader选举
  2. 日志的复制(Log replication)
  3. Safty: 不能有错误数据
  • Raft的实践基础
    一个Raft集群会有多个节点, 一般至少5个, 这样可以忍受2个节点fail。 这些节点在任何时间点都会是以下3个状态之一: leader, follower, candidate。
    Raft将时间分为了多个term, 选举会产生一个新的term, 每个term的时长不定,但是每个term都至多有一个leader
    不同的节点会在不同时间感知到变化,有些节点甚至在一个term完结时都没有感知到。 Terms是一个逻辑时钟, 每个节点都会存储当前term, 并且会一直跟别的节点交换信息, 一旦发现自己的term不是最新的, 就会更新term, 如果一个candidate或者leader发现他的term过时了,就会马上回退成follower。 如果一个节点收到一个过期term的请求, 那么他会拒绝这个请求
    Raft节点间通过RPC请求进行通信, 基本的算法只要求两种RPC请求类型。 一种是RequestVote RPCs, 由candidate在选举时发出。 一种是AppendEntries RPCs, 由leader发出, 用来复制log和发送心跳

  • leader选举
    Raft用心跳来触发leader选举, 当节点启动时, 都是follower的状态。只要节点能够收到来自leader或者candidate的RPC, 节点就会保持follower状态。
    Leader会定期发送RPC给所有的follower来维持他的leader地位, 但是一旦有一个节点在一段时间没有收到心跳, 那么节点就会认为没有存活的leader并且触发新一次的选举。
    选举开始时,一个follower会给当前term加1并且转换成candidate状态。 然后这个节点会给自己投票并且给所有其他节点发送RequestVote RPC。
    Candidate会保持这个状态直到以下3个事件中的一个发生:

    1. 这个节点赢得选举
      如果这个节点赢得了半数以上的vote就会成为leader,每个节点会按照first-come-first-served的原则进行投票,并且一个term中只能投给一个节点, 这样就保证了一个term最多有一个节点赢得半数以上的vote。
      当一个节点赢得选举, 他会成为leader, 并且给所有节点发送这个信息, 这样所有节点都会回退成follower。
    2. 另外一个节点赢得选举
      在等待vote时, 如果这个candidate收到了别的节点请求vote的RPC, 那么他会检查是否这个节点的term大于等于自己的term, 如果是那么这个candidate就会回退成follower。 如果不是就会reject这个RPC。
    3. 一个选举周期结束并且没有leader选出来
      这种情况是由于可能有很多follower都成为了candidate, 那么vote就会很分散, 最后没有一个节点拿到半数以上的vote。最后这个term超时并且进入下个term继续选举。
      为了防止这种情况一直重复,每个节点的election 超时时间是(150~300ms)的随机数, 这样在一个term就会有一个节点很快超时进入下一个term, 然后就能在别的节点timeout之前赢得选举
Figure3
  • Log replication
    当leader选出来后,他就可以正式给客户端提供服务。 leader会将请求以entry的形式追加到自己的log中,并且将这个entry以AppendEntries RPC并发发送给所有的follower节点。 当这个entry成功的复制后(怎么算成功之后会谈到), leader会将这个entry 应用到自己的state machine并且给client返回成功。 如果复制失败, leader会一直重试AppendEntries RPC直到所有log entry都被成功复制。
Logs Organization

Logs 组织的形式如图所示。 当leader收到一个Log entry时, 每个log entry都会存储一个带有term number的state machine命令。 Term number是用来探测log之间的不一致性并且保证Figure3的一些特性。 每个log也还带有他们在log里的索引数字。

当leader认为这个entry是可以成功应用到状态机上, 那么这个entry就被成为commited。Raft保证所有commited entry最终都会被应用到所有的节点上。

当一个entry被成功复制到半数以上的节点后, 这个log就可以认为成功写入了。并且会将leader之前的写入也视为commit。

设计Raft日志机制不仅简化了系统的行为, 也保证了正确性。 保证了Figure3的以下特性
1. 当不同log中的两个entry有相同的term和index, 那么这两个entry就是相同的
2. 当不同log中的两个entry有相同的term和index, 那么这两个entry之前的所有entry也都是相同的

Paste_Image.png

当leader发现follower的log跟自己的不同时, 他会针对每个follower维护一个nextIndex。 这个nextIndex就是Leader下次会发第几个entry给这个follower。 而follower也会拒绝这个append entry的rpc。

Safety

  • 如何保证数据不丢失和数据的正确性是分布式数据库最重要的两点, Raft协议也设计了相应的算法来保证这两点。
    1. 所有的entry都只能从leader流向follower,而要成为leader必须有所有的committed entries。 如果有server发现candidate的数据没有自己更update-to-date, 那么他会拒绝这个vote request。 如果两个server的log term不同, 那么term number更大的更update-to-date, 如果term相同, 那么index更大的更update-to-date。
Figure 3
  1. 仅有第一点的保证我们仍旧可能会遇到问题。 如上图所示, a) s1成为leader,部分拷贝了index 2; b) s1挂了, s5成为leader, 写入index 3; c)s5又挂了, s1再次成为leader并且继续将index 2拷贝到其余follower; d) s1又一次挂了, s5成为leader(获得2,3,4的选票), 将自己所有的s3拷贝到别的机器并且覆盖掉了index 2; e)如果c阶段没有挂那么日志会被拷贝到s2,s3, 之后s5就不会被选为leader。
    上图演示了写入数据可能会被覆盖的问题, 那么如何避免这个问题。 Raft规定绝不通过计算副本数的方式commit 之前term的log entries。 只有当前term的log enties使用计算副本的方式来提交。 对于之前的term来说,当一个log通过这个方式提交成功了,那么他之前的所有log都算commit成功了。

    如何证明这个结论的正确性, 论文用反证法进行了论证:

Figure 4

如Figure 4所示, 如果term T commit的数据在之后的term U丢失了, 那么
1. 这个log一定不在Leader-U的log中(因为leader不会覆盖旧数据)
2. Leader-T把这个日志复制给了大多数节点并且Leader-U收到了大多数节点的投票, 所以至少有一个节点是既收到了这个entry并且又给Leader-U投票了
3. 那么这个投票的节点也一定收到了所有Leader-T的commited entries
4. 因为这个投票节点把票投给了U, 那么说明Leader-U也至少有所有这个节点的entries
由此可知, 如果投票节点和Leader-U 共享了之前的log, 那么Leader-U肯定会有所有投票节点的entry。 另外, Leader-U的last-log-term必须比T大, 而投票节点的term至少是T。之前term的leader在复制entry给Leader-U时也必须包含了之前的这个entry。 投票节点和之前term的leader都会有这个entry, 所以Leader-U也不会没有这个entry。可下结论所有大于T的term的leader绝对包含了所有term T commited的entries。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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

推荐阅读更多精彩内容