Raft论文简述

目的

根据《In Search of an Understandable Consensus Algorithm》论文的描述来看,Raft和Paxos这些共识算法是为了解决分布式系统里状态机同步的问题。最典型的应用就是分布式里的容错,所有的server都应该要有备份,如果是带状态的server(典型的如kv server),那么master和secondary之间的数据如何保持一致不会出错就是一个难题,而这些共识算法就是为了解决这类问题的。

前言

一般来说状态机同步有以下两种方案。

1.State Transfer。将完整的状态同步。

2.Replicated State Machine。假设没有外因的情况下,对一样的状态机输入一样的数据,那么他输出的数据也是一样的,即只要保持输入一致那么状态机的最终态也是一致的。而Raft采取的是这个方案。

概念

Raft中的所有节点在某个时刻必定处于以下三种状态中的一种:

Leader:接受客户端的请求,将数据同步给其他Server。
Follower:接受Leader或者Candidate的请求进行处理。
Candidate:选举中的可能成为Leader的一个状态。

Term: 任期。这是一个随时间单调递增的变量,每个Term都是由选举开始的,Raft保证一个Term最多选出一个Leader。任何一个Server在观察到自己的Term过期后会更新Term并且转换为Follower状态。

这个算法可以保证以下结论:
 1.在给定的Term中最多只会选出一个Leader。
 2.对于Leader来说,它永远只会做添加日志操作,不会做删除或者覆盖日志操作。
 3.如果两条Log拥有相同的Index和Term那么认为这条Log以及这条Log之前的所有Log都是相同的。
 4.如果一条Log已经提交,那么这条Log会在出现在所有Term大于该Term的leader的Log中。
 5.如果一个Server将某索引为Index的一条记录提交到状态机,那么其他Server不能将同一个Index的不同记录提交到状态机。

实现

Raft主要通过两个RPC方法来实现。
RequestVote:Candidate在选举过程中使用的,用于请求投票。
AppendEntries:Leader进行Log复制和Heartbeat时候用的。

Raft的一致性问题可以拆分成三个子问题:Leader选举,日志复制,安全性。

Leader选举

Leader选举是通过Heartbeat机制触发的。具体体现在AppendEntries RPC方法。启动的时候所有Server都是Follower状态,当Follower的计时器超时都没收到Leader的Heartbeat时,它就会假设集群里没有Leader,转换成Candidate状态发起选举。

选举开始时,Follower会首先自增Term,然后切换到Candidate状态。同时它会给自己投票,并向其他服务器发起RequestVote RPC请求以获得投票支持。它会保持Candidate状态直到发生以下三种情况之一:
 1.胜出选举。此时,它会切换到Leader状态,并立即调用AppendEntries RPC进行Hearbeat操作,阻止发起下一轮选举。
 2.某个Server宣告自己已成为Leader。此时需区分两种情况:如果该Server的Term>=自己的Term,则认为其声明合法的,Candidate切换到Follower状态;若不满足此条件,则认为其声明不合法,继续保持Candidate状态。
 3.选举超时,没有产生胜者。在这种情况下,将重新发起一轮选举。

在此过程中,我们容易注意到一个问题:如果没有经过特殊处理,所有Server同时发起选举的可能性很高。这将导致每个Server都给自己投票,而无法产生胜出的Leader。为解决这一问题,Raft算法引入了随机性操作,对选举超时时间进行一定范围的随机化处理。这样便能在很大程度上保证选举过程中,有Server能够胜出成为Leader。

日志复制

前文提到,Raft算法采用了Replicated Machine的方式,通过复制Log来确保输入一致性。同步操作由Leader发起的,每当Leader处理Client的请求(即状态机的一条命令Command)时,Leader会将Command追加到自己的Log中,然后发起AppendEntries RPC请求,直到Log被安全复制。Log应包含Term和Command信息,其中Term用于进行一致性检查。一旦Leader提交了一条Log,我们称为这条Log是Committed状态。当这条Log被复制到大多数Server时,那么称这条Log是提交的。Raft算法会确保已提交的日志应用到其他状态机上。
Leader维护了一个可提交日志的索引Index,并在AppendEntries RPC中携带此信息,告知Follower应提交此索引之前的所有记录。Leader在发送AppendEntries的时候会包含当前复制记录的前驱记录的Index和Term,如果Follower发现没有相同的前驱记录,它会拒绝该请求。如果Follower拒绝请求,证明Leader和Follower的Log不一致,此时,Leader会强制要求Follower同步成Leader的数据,Leader通过不断执行Index-1操作发起请求直到找到最后一条一致的记录。然后,Leader会将该记录之后的所有记录通过AppendEntries RPC同步给Follower。
需要注意的是,这里的每次Index-1操作可能存在效率问题。在实际工程实现中,可以进行优化。然而,作者本人对优化的必要性表示怀疑,因为这种事件发生的概率极低。

安全性

Leader宕机:
如上图,存在这么一种情况,在图a时候,Leader是S1,此时刚开始复制Log2,但在还未复制到大多数节点之前就宕机了。在图b时,S5选举成为新的Leader,将Log3添加到本地后宕机了。到图c时,S1重新成为Leader,将Log2复制到了大多数节点并提交。此时,如果S1再次宕机,且c成为了Leader,会出现图d的情况,把Log3覆盖原来Log2的位置,但是S1已经把Log2提交到了自己的状态机,此时便会发生状态机不一致的问题。为了避免这一问题,Raft算法增加了选举约束:如果Follower的日志比Candidate的日志更新,那么Follower应拒绝这次投票。Log比较的优先级顺序是先比较Term,再比较Index。此外,新Leader在重新选举出来后,不能直接提交非本任期以内的日志,因为无法确定这些日志是否复制到了大多数节点,需要等到下一个本任期内的新日志提交来保护前面的日志。


Follower和Candidate宕机:Leader持续重试RPC操作,直至它们恢复,Raft的RPC操作是可重入无危害的。

快照

为解决数据严重滞后的Server的问题,采用大量的RPC请求相较于直接发送整个状态机的状态来说并不高效。因此,通常每个Server可以在固定的n条日志提交后进行一次快照操作。具体参数的选择取决于机器性能以及应用场景。

集群成员变更

集群成员变更的难点在于变更过程中不能出现两个Leader,作者首先提出来Joint Consensus的实现,后来又提出更简单的Single-server Changes的实现,即通过单节点变更来解决这个问题。由于Joint Consensus过于复杂,且在工程中大多数都使用Single-server Changes,因此这里仅讨论Single-server Changes的原理。

上图分别展示了4种情况。
 a:偶数节点增加一个节点。
 b:奇数节点增加一个节点。
 c:奇数节点减少一个节点。
 d:偶数节点减少一个节点。
可以观察到,在单节点变更下,无论是哪一种情况,新旧配置中的大多数节点总会存在一个交集节点。由于Follower只能给一个Server投票,因此不会有多个节点满足大多数节点的投票要求,最多只会产生一个Leader。

预投票

Prevote预投票是作者在另一篇论文《CONSENSUS: BRIDGING THEORY AND PRACTICE》中提及的概念,主要用于解决以下问题。

假设存在一种情况,我们有5个Server分别为S1至S5,其中S1是Leader。连线表示两个Server之间网络是联通的。S5无法收到Leader S1的心跳,此时会发起一次新的选举,获得了S2,S3,S4的投票,成为了新的Leader。S1意识到了有新的Term产生,会转换为Follower,但又收不到S5的心跳,因此会陷入反复发起选举的现象。
还有一种情况,假设图上S5是个孤立的节点,它会反复发起新的选举导致Term不断增加变得非常大。当它重新与其他节点联通时,集群内的所有节点都会受到这个旧节点的干扰。
预投票机制就是为了解决这些问题而设计的。在预投票算法中,Candidate首先要确认自己能赢得集群中大多数节点的投票,这样才会把自己的Term增加,然后发起真正的投票。其他投票节点同意发起选举的条件如下:
 1.没有收到有效领导的心跳,至少有一次选举超时。
 2.Candidate的日志足够新(Term更大,或者Term相同Log Index更大)。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Raft算法是一种分布式一致性算法,主要解决分布式系统中的数据一致性问题。Raft算法解决了三个子问题,分别是领导选举、日志复制和安全性问题。 1. 领导选举: Raft算法中,任何时刻只有一个节点可以充当领导,其他节点则作为跟随者。当领导节点失效时,需要重新选举出一个新的领导。Raft算法通过引入随机定时器和选票来实现领导选举。当跟随者节点在一定时间内没有收到领导节点的心跳信号时,就会启动选举过程。选举过程中,每个节点会给自己投票,并向其他节点发送投票请求。如果某个节点收到了超过半数的投票,则该节点成为新的领导。 2. 日志复制: Raft算法中的每个节点都有自己的日志,领导节点负责向跟随者节点复制日志。当领导节点接收到客户端发来的请求时,会将该请求作为一条日志记录在自己的日志中,并向其他跟随者节点广播该日志。一旦跟随者节点收到日志,并将其复制到自己的日志中,就会向领导节点发送确认消息。一旦领导节点收到了超过半数的确认消息,就会提交该日志并将其应用到状态机中。 3. 安全性问题: Raft算法通过引入领导节点来保证安全性。任何更新都必须经过领导节点,跟随者节点只能从领导节点复制日志。同时,Raft算法中的日志是按照顺序递增的,领导节点只会提交日志中最新的一条记录,这样就能保证数据的一致性和正确性。此外,Raft算法还引入了多数派原则,只有当超过半数的节点同意某个更新时,该更新才能被提交。这样就能避免分裂大多数节点的情况,确保系统的安全性和一致性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值