RAFT算法

Raft是用于管理复制日志的一致性算法,raft 协议也是一个主备模型,有一个唯一的 leader 控制任务的提交。

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

在Raft中,问题分解为:领导选取、日志复制、安全和日志压缩。

基本概念

服务器状态

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

  • follower(跟随者) :所有结点都以 follower 的状态开始。如果没收到 leader消息则会变成 candidate状态。

  • candidate(候选人):会向其他结点“拉选票”,如果得到大部分的票则成为leader。这个过程就叫做Leader选举(Leader Election)。

  • leader(领导者):所有对系统的修改都会先经过leader

image-20210902104942439.png

任期(Term)

raft 最关键的一个概念是任期,用以解决“时间同步”的问题,每一个 leader 都有自己的任期,必须在任期内发送心跳信息给 follower 来延长自己的任期。

1、每个Term至多存在1个Leader

2、 某些Term由于选举失败,不存在Leader

3、 每个Server本地维护currentTerm

image-20210902112928152.png

RPC

RPC有三种:

  1. RequestVote RPC:候选人在选举期间发起

  2. AppendEntries RPC:领导人发起的一种心跳机制,复制日志也在该命令中完成

  3. InstallSnapshot RPC: 领导者使用该RPC来发送快照给太落后的追随者。

Leader election (领导选举)

Raft 使用心跳机制来触发领导人选举。当服务器程序启动时,他们都是 follower(跟随者) 身份,如果跟随者在超时时间(每一个节点会自定义一个超时时间)内没有收到 Leader 的请求则转换为 Candidate 进行选举。在一次选举过程,每一个 Candidate 首先term加一,并且投自己一票。

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

  1. 获得超过半数服务器的投票,赢得选举,成为领导者;

  2. 另一台服务器赢得选举,并接收到对应的心跳,成为追随者;

  3. 选举超时,没有任何一台服务器赢得选举,自增当前任期,重新发起选举;

注意事项:

  1. 服务器在一个任期内,最多能给一个候选人投票,采用先到先服务原则;

  2. 候选者等待投票时,可能会接收到来自其它声明为领导人的的AppendEntries RPC。如果该领导人的任期(RPC中有)比当前候选人的当前任期要大,则候选人认为该领导人合法,并转换成追随者;如果RPC中的任期小于候选人的当前任期,则候选人拒绝此次RPC,继续保持候选人状态;

  3. 候选人既没有赢得选举也没有输掉选举:如果许多追随者在同一时刻都成为了候选人,选票会被分散,可能没有候选人能获得大多数的选票。当这种情形发生时,每一个候选人都会超时,并且通过自增任期号和发起另一轮 RequestVote RPC 来开始新的选举。然而,如果没有其它手段来分配选票的话,这种情形可能会无限的重复下去。所以Raft使用的随机的选举超时时间(150~300ms之间),来避免这种情况发生。

Log replication (日志复制)

image-20210902151021539.png

接受命令的过程:

  1. 领导者接受客户端请求;

  2. 领导者把指令追加到日志;

  3. 发送AppendEntries RPC到追随者;

  4. 领导者收到大多数追随者的确认后,领导者Commit该日志,把日志在状态机中回放,并返回结果给客户端;

提交过程:

  1. 在下一个心跳阶段,领导者再次发送AppendEntries RPC给追随者,日志已经commited;

  2. 追随者收到Commited日志后,将日志在状态机中回放。

follower 宕机或者运行较慢时,leader 会无限地重发AppendEntries给这些follower(尽管已经回复了客户端),直到所有的follower都复制了该log entry。

Raft的log replication保证以下性质(Log Matching Property):

  • 如果在不同的日志中的两个条目拥有相同的索引和任期号,那么他们存储了相同的指令。

  • 如果在不同的日志中的两个条目拥有相同的索引和任期号,那么他们之前的所有日志条目也全部相同。

其中特性一通过以下保证:

  • leader在一个特定的term和index下,只会创建一个log entry

  • log entry不会改变它们在日志中的位置

特性二通过以下保证:

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

  • 如果follower没有发现与它一样的log entry,那么它会拒绝接受新的log entry。

不一致场景:某服务器在任期 2 的时候是领导人,已附加了一些日志条目到自己的日志中,但在提交之前就崩溃了;很快这个机器就被重启了,在任期 3 重新被选为领导人,并且又增加了一些日志条目到自己的日志中;在任期 2 和任期 3 的日志被提交之前,这个服务器又宕机了,并且在接下来的几个任期里一直处于宕机状态。

image-20210902142937422.png

在 Raft 算法中,领导人处理不一致是通过强制跟随者直接复制自己的日志来解决了。这意味着在跟随者中的冲突的日志条目会被领导人的日志覆盖。要使得跟随者的日志进入和自己一致的状态,领导人必须找到最后两者达成一致的地方,然后删除从那个点之后的所有日志条目,发送自己的日志给跟随者。

在数据同步阶段,可能出现六种情况:

  • 数据到达 Leader节点前,Leader 挂掉。

    • 这个阶段 Leader 挂掉不影响一致性。
  • 数据到达 Leader节点,但未复制到 Follower节点,Leader挂掉。

    • 这个阶段 Leader 挂掉,数据属于未提交状态,Client 不会收到 Ack 会认为超时失败可安全发起重试Follower 节点上没有该数据,重新选主后 Client 重试重新提交可成功。原来的 Leader 节点恢复后作为 Follower 加入集群重新从当前任期的新 Leader 处同步数据,强制保持和 Leader 数据一致。
  • 数据到达 Leader节点,成功复制到 Follower所有节点,但还未向 Leader响应接收,Leader挂掉。

    • 这个阶段 Leader 挂掉,虽然数据在 Follower 节点处于未提交状态(Uncommitted)但保持一致,重新选出 Leader 后可完成数据提交,此时 Client 由于不知到底提交成功没有,可重试提交。针对这种情况 Raft 要求 RPC 请求实现幂等性,也就是要实现内部去重机制。(类似于 zab)
  • 数据到达 Leader节点,成功复制到Follower部分节点,但还未向 Leader响应接收,Leader挂掉。

    • 这个阶段 Leader 挂掉,数据在 Follower 节点处于未提交状态(Uncommitted)且不一致,Raft 协议要求投票只能投给拥有最新数据的节点。所以拥有最新数据的节点会被选为 Leader 再强制同步数据到 Follower,数据不会丢失并最终一致。
  • 数据到达 Leader节点,成功复制到 Follower所有或多数节点,数据在 Leader处于已提交状态,但在 Followe处于未提交状态,Leader挂掉。

    • 这个阶段 Leader 挂掉,重新选出新 Leader 后的处理流程和第三种情况一样。
  • 网络分区导致的脑裂情况,出现双 Leader

    • 原先的 Leader 独自在一个区,向它提交数据不可能复制到多数节点所以永远提交不成功。向新的 Leader 提交数据可以提交成功,网络恢复后旧的 Leader 发现集群中有更新任期(Term)的新 Leader 则自动降级为 Follower 并从新 Leader 处同步数据达成集群数据一致。

安全性

领导者追加日志(Append-Only)

领导者永远不会覆盖已经存在的日志条目; 日志永远只有一个流向:从领导者到追随者;

选举限制:投票阻止没有全部日志条目的服务器赢得选举

如果投票者的日志比候选人的新,拒绝投票请求; 这意味着要赢得选举,候选者的日志至少和大多数服务器的日志一样新,那么它一定包含全部的已经提交的日志条目。

永远不提交任期之前的日志条目(只提交任期内的日志条目)

在Raft算法中,当一个日志被安全的复制到绝大多数的机器上面,即AppendEntries RPC在绝大多数服务器正确返回了,那么这个日志就是被提交了,然后领导者会更新commit index。

image-20210902145353901.png

如果允许提交任期之前的日志条目,那么在步骤c中,我们就会把之前任期为2的日志提交到其他服务器中去,并造成了大多数机器存在了日志为2的情况。所以造成了d中S5中任期为3的日志条目会覆盖掉已经提交的日志的情况。

Raft 从来不会通过计算复制的数目来提交之前人气的日志条目。只有领导人当前任期的日志条目才能通过计算数目来进行提交。一旦当前任期的日志条目以这种方式被提交,那么由于日志匹配原则(Log Matching Property),之前的日志条目也都会被间接的提交。

论文中的这段话比较难理解,更加直观的说:由于Raft不会提交任期之前的日志条目,那么就不会从b过渡到c的情况,只能从b发生S5down机的情况下直接过渡到e,这样就产生的更新的任期,这样S5就没有机会被选为领导者了。

跟随者和候选人崩溃

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

  • 领导者会不断给它发送选举和追加日志的RPC,直到成功

  • 跟随者会忽略它已经处理过的追加日志的RPC

日志压缩

raft采用快照的方式进行日志压缩,做完快照之后快照会在稳定持久存储中保存,而快照之前的日志和快照就可以丢弃掉


image-20210902161308936.png

与Raft其它操作Leader-Based不同,snapshot是由各个节点独立生成的。除了日志压缩这一个作用之外,snapshot还可以用于同步状态:slow-follower以及new-server,Raft使用InstallSnapshot RPC完成该过程。

动画演示 Raft

http://thesecretlivesofdata.com/raft/

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

推荐阅读更多精彩内容