raft简单介绍

一致性算法 - Raft

Raft 状态

一个 Raft 集群包含若干个服务器节点;一般是 5 个,这容许整个系统容忍 2 个节点的失效,每一个节点处于如下三种状态之一:算法

  • follower(跟随者) :全部结点都以 follower 的状态开始。若是没收到 leader消息则会变成 candidate状态。
  • candidate(候选人):会向其余结点“拉选票”,若是获得大部分的票则成为leader。这个过程就叫作Leader选举(Leader Election)。
  • leader(领导者):全部对系统的修改都会先通过leader

Raft 一致性算法

Raft经过选出一个leader来简化日志副本的管理,例如,日志项(log entry)只容许从leader流向follower。安全

基于leader的方法,Raft算法能够分解成三个子问题:服务器

Leader election (领导选举):原来的leader挂掉后,必须选出一个新的leader动画

Log replication (日志复制):leader从客户端接收日志,并复制到整个集群中spa

Safety (安全性):若是有任意的server将日志项回放到状态机中了,那么其余的server只会回放相同的日志项日志

Leader election (领导选举)

Raft 使用一种心跳机制来触发领导人选举。当服务器程序启动时,他们都是 follower(跟随者) 身份。若是一个跟随者在一段时间里没有接收到任何消息,也就是选举超时,而后他就会认为系统中没有可用的领导者而后开始进行选举以选出新的领导者。要开始一次选举过程,follower 会给当前term加1而且转换成candidate状态。code

而后他会并行的向集群中的其余服务器节点发送请求投票的 RPCs 来给本身投票。候选人的状态维持直到发生如下任何一个条件发生的时候,server

  • 他本身赢得了此次的选举rem

    • 若是这个节点赢得了半数以上的vote就会成为leader,每一个节点会按照first-come-first-served的原则进行投票,而且一个term中只能投给一个节点, 这样就保证了一个term最多有一个节点赢得半数以上的vote。
    • 当一个节点赢得选举, 他会成为leader, 而且给全部节点发送这个信息, 这样全部节点都会回退成follower。
  • 其余的服务器成为领导者get

    若是在等待选举期间,candidate接收到其余server要成为leader的RPC,分两种状况处理:

    • 若是leader的term大于或等于自身的term,那么改candidate 会转成follower 状态
    • 若是leader的term小于自身的term,那么会拒绝该 leader,并继续保持candidate 状态
  • 一段时间以后没有任何一个获胜的人

    • 有可能,不少follower同时变成candidate,致使没有candidate能得到大多数的选举,从而致使没法选出主。当这个状况发生时,每一个candidate会超时,而后从新发增长term,发起新一轮选举RPC。须要注意的是,若是没有特别处理,可能出致使无限地重复选主的状况。
    • Raft采用随机定时器的方法来避免上述状况,每一个candidate选择一个时间间隔内的随机值,例如150-300ms,采用这种机制,通常只有一个server会进入candidate状态,而后得到大多数server的选举,最后成为主。每一个candidate在收到leader的心跳信息后会重启定时器,从而避免在leader正常工做时,会发生选举的状况。

Log replication (日志复制)

当选出 leader 后,它会开始接受客户端请求,每一个请求会带有一个指令,能够被回放到状态机中。leader 把指令追加成一个log entry,而后经过AppendEntries RPC并行的发送给其余的server,当改entry被多数派server复制后,leader 会把该entry回放到状态机中,而后把结果返回给客户端。

follower 宕机或者运行较慢时,leader 会无限地重发AppendEntries给这些follower,直到全部的follower都复制了该log entry。

raft的log replication保证如下性质(Log Matching Property):

  • 若是两个log entry有相同的index和term,那么它们存储相同的指令
  • 若是两个log entry在两份不一样的日志中,而且有相同的index和term,那么它们以前的log entry是彻底相同的

其中特性一经过如下保证:

  • leader在一个特定的term和index下,只会建立一个log entry
  • log entry不会改变它们在日志中的位置

特性二经过如下保证:

  • AppendEntries会作log entry的一致性检查,当发送一个AppendEntriesRPC时,leader会带上须要复制的log entry前一个log entry的(index, iterm)

若是follower没有发现与它同样的log entry,那么它会拒绝接受新的log entry 这样就能保证特性二得以知足。

安全性

选举限制

在一些一致性算法中,即便一台server没有包含全部以前已提交的log entry,也能被选为主,这些算法须要把leader上缺失的日志从其余的server拷贝到leader上,这种方法会致使额外的复杂度。相对而言,raft使用一种更简单的方法,即它保证全部已提交的log entry都会在当前选举的leader上,所以,在raft算法中,日志只会从leader流向follower。

为了实现上述目标,raft在选举中会保证,一个candidate只有获得大多数的server的选票以后,才能被选为主。获得大多数的选票代表,选举它的server中至少有一个server是拥有全部已经提交的log entry的,而leader的日志至少和follower的同样新,这样就保证了leader确定有全部已提交的log entry。

提交以前任期内的日志条目

领导人知道一条当前任期内的日志记录是能够被提交的,只要它被存储到了大多数的服务器上。若是一个领导人在提交日志条目以前崩溃了,将来后续的领导人会继续尝试复制这条日志记录。然而,一个领导人不能判定一个以前任期里的日志条目被保存到大多数服务器上的时候就必定已经提交了。下图展现了一种状况,一条已经被存储到大多数节点上的老日志条目,也依然有可能会被将来的领导人覆盖掉。

如上图的例子,图(c)就发生了一个log entry虽然已经复制到大多数的服务器,可是仍然有可能被覆盖掉的可能,如图(d),整个发生的时序以下:

  • 图a中,S1被选为主,而后复制到log index为2的log entry到S2上
  • 图b中,S1挂掉,而后S5得到了S3,S4和自身的选举,成为leader,而后,其从客户端收到了一个新的log entry(3)
  • 图c中,S5挂掉,S1从新正常工做,又被选为主,继续复制log entry(2),在log entry(2)被提交前,S1又挂掉
  • 图d中,S5又从新被选为领导者,而后,会把term 3的log entry覆盖到其余log index为2的log entry

为了上图描述的状况,Raft 永远不会经过计算副本数目的方式去提交一个以前任期内的日志条目。只有领导人当前任期里的日志条目经过计算副本数目能够被提交;一旦当前任期的日志条目以这种方式被提交,那么因为日志匹配特性,以前的日志条目也都会被间接的提交。例如,图e中,若是S1在挂掉前把log entry(4)复制到了大多数的server后,就能保证以前的log entry(2)被提交了,以后S5也就不可能被选为领导者了。

安全性论证

以反证法来证实,假设任期 T 的领导人(领导人 T)在任期内提交了一条日志条目,可是这条日志条目没有被存储到将来某个任期的领导人的日志中。设大于 T 的最小任期 U 的领导人 U 没有这条日志条目。

若是 S1 (任期 T 的领导者)提交了一条新的日志在它的任期里,而后 S5 在以后的任期 U 里被选举为领导人,而后至少会有一个机器,如 S3,既拥有来自 S1 的日志,也给 S5 投票了。
  1. 在领导人 U 选举的时候必定没有那条被提交的日志条目(领导人从不会删除或者覆盖任何条目)。
  2. 领导人 T 复制这条日志条目给集群中的大多数节点,同时,领导人U 从集群中的大多数节点赢得了选票。所以,至少有一个节点(投票者、选民)同时接受了来自领导人T 的日志条目,而且给领导人U 投票了,这个投票者是产生这个矛盾的关键。
  3. 这个投票者必须在给领导人 U 投票以前先接受了从领导人 T 发来的已经被提交的日志条目;不然他就会拒绝来自领导人 T 的附加日志请求(由于此时他的任期号会比 T 大)。
  4. 投票者在给领导人 U 投票时依然保有这条日志条目,由于任何中间的领导人都包含该日志条目(根据上述的假设),领导人从不会删除条目,而且跟随者只有和领导人冲突的时候才会删除条目。
  5. 投票者把本身选票投给领导人 U 时,领导人 U 的日志必须和投票者本身同样新。这就致使了二者矛盾之一。

    • 首先,若是投票者和领导人 U 的最后一条日志的任期号相同,那么领导人 U 的日志至少和投票者同样长,因此领导人 U 的日志必定包含全部投票者的日志。这是另外一处矛盾,由于投票者包含了那条已经被提交的日志条目,可是在上述的假设里,领导人 U 是不包含的。
    • 除此以外,领导人 U 的最后一条日志的任期号就必须比投票人大了。此外,他也比 T 大,由于投票人的最后一条日志的任期号至少和 T 同样大(他包含了来自任期 T 的已提交的日志)。建立了领导人 U 最后一条日志的以前领导人必定已经包含了那条被提交的日志(根据上述假设,领导人 U 是第一个不包含该日志条目的领导人)。因此,根据日志匹配特性,领导人 U 必定也包含那条被提交固然日志,这里产生矛盾。
  6. 所以,假设不成立,全部比 T 大的领导人必定包含了全部来自 T 的已经被提交的日志。日志匹配原则保证了将来的领导人也同时会包含被间接提交的条目

跟随者和候选人崩溃

跟随者或者候选人崩溃,会按以下处理:

  • 领导者会不断给它发送选举和追加日志的RPC,直到成功
  • 跟随者会忽略它已经处理过的追加日志的RPC

时间和可用性

领导人选举是 Raft 中对时间要求最为关键的方面。Raft 能够选举并维持一个稳定的领导人,只要系统知足下面的时间要求:

广播时间(broadcastTime) << 选举超时时间(electionTimeout) << 平均故障间隔时间(MTBF)
  • 广播时间指的是从一个服务器并行的发送 RPCs 给集群中的其余服务器并接收响应的平均时间;
  • 选举超时时间就是选举的超时时间限制
  • 平均故障间隔时间就是对于一台服务器而言,两次故障之间的平均时间。

选举超时时间要大于广播时间的缘由是,防止跟随者由于还没收到领导者的心跳,而从新选主。

选举超时时间要小于MTBF的缘由是,防止选举时,能正常工做的server没有达到大多数。

对于广播时间,通常在[0.5ms,20ms]之间,而平均故障间隔时间通常很是大,至少是按照月为单位。所以,通常选举超时时间通常选择范围为[10ms,500ms]。所以,当领导者挂掉后,能在较短期内从新选主。

动画演示 Raft

http://thesecretlivesofdata.c...

相关文章
相关标签/搜索