Raft详解(In Search of an Understandable Consensus Algorithm (Extended Version)翻译)

In Search of an Understandable Consensus Algorithm (Extended Version)

1. 一致性算法的特征:

  • 在所有的非拜占庭条件下保证安全(不会返回一个错误的结果),包括网络延时,分区,包丢失,复制,重新排序。
  • 只要大多数服务器能够相互通信并且连接客户端,则可用;
  • 不依赖于时间保证日志的一致性,因为错误的时钟或者及其大的消息时延在最坏的情况下能够导致可用性问题;
  • 通常,只要集群中的大多数服务器回应了单个的RPC,一次命令就算完成;大多数服务器的缓慢不会影响系统的整体性能。

拜占庭条件和非拜占庭条件:
分布式领域一个著名的问题: 拜占庭将军问题。 指的是有 n n n 个将军需要就战争决策达成一致,但其中某些将军可能是叛徒,因此会千方百计的阻止他们达成一致,包括发送虚假的信息。这些将军可以采取的方法有:欺骗,混淆。拜占庭条件指的是叛徒可能会采取所有的手段阻止决策达成一致,包括欺骗;而非拜占庭条件则去除了欺骗这一手段。

2. Raft

复制状态机 :Raft的总体模型如上图所示。

Raft将一致性问题分为三个子问题:

  • leader选举: 当当前的leader失败后新的leader必须被选举出来;
  • 日志复制: leader必须从客户端接收日志并将其在集群中复制,确保其他日志与其相同;
  • 安全: Raft最主要的安全特性是复制状态机的特性:如果任何一个服务器将一个特殊的日志应用到其复制状态机,那么没有服务器在当前的日志索引下应用其他的日志;

安全包括:

  • 选举安全: 最多一个leader被选举出来;
  • leader只追加日志: leader不会删除和重写其含有的日志;
  • 日志匹配: 如果两个日志包含具有相同索引和时期的条目,则日志在给定索引之前的所有条目中都是相同的。
  • leader完整性: 在给定的时期,一个日志被提交,那么该日志在其他更高数字的时期的leader上也存在;
  • 状态机安全性: 如果一台服务器在给定的索引下应用了一个日志,那么没有其他的状态机在相同的索引下应用其他的日志;

2.1 Raft基础

奇数台服务器,每台服务器有三种状态:leader,follower和candidate。

  • leader: leader处理所有客户端请求(如果一个客户端请求follower,follower将该请求重定向到leader)
  • follower: follower只处理来自于leader的请求;
  • candidate: 用于选举一个新leader。

状态之间的转换如下图所示:

单节点状态转换图

Raft将时间分为任意长度的时期,时期通过连续的数字标识:

每个时期以选举开始,此时一或多个candidator尝试成为leader;如果有一个赢得了选举,那么其成为当前时期的leader;如果出现了分离的选票(即没有一个candidator赢得选举),那么该时期结束,下一个时期开始;有些服务器不会观察到term的转换,因此这些服务器被丢弃(因为持有了旧数据)。

每一个服务器都有一个单调递增的current term number,在两台服务器通信时就会被交换;

  • 如果一台服务器的current term number小于另一台服务器,则当前服务器更新自己的current term number为一个更大的值;
  • 如果candidate/leader发现他的时期已经过期,那么其立刻将其状态转换为follower。
  • 如果一台服务器收到的请求的current term number比自己所持有的小,则拒绝这个请求;

服务器间通过RPC通信;三种类型的RPC:RequestVote用于candidate请求投票;AppendEntries用于leader追加日志;第三种类型的RPF用于传输快照;RPC在特定时期没有收到回答时会重试;RPC是并行以提高性能。

2.2 Leader 选举

服务器刚启动时是follower状态;只要其收到leader和candidate的RPC请求,那么其一直保持follower状态;Leader向follower发送心跳(没有日志的AppendEntries RPC)保持其权威;如果在一定时间后其没有收到RPC,则其认为没有可行的leader并开始一个选举产生新的leader;

开始选举时,其增加他的current term number,状态改变为candidate,给自己投一票,并且并行向其他server发送RequestVote RPC以请求他们为自己投票。candidate状态持续直到:

  1. **其赢得了选举:**如果一个candidate收到了大多数服务器的投票则认为赢得了选举;在一个时期内follower通过先到先得的方式只会给一个candidate投票(还有其他条件);如果一个candidate赢得了选举,其立刻向其他server发送心跳确保权威和阻止其他的candidate选举。
  2. 另一个服务器宣布其为leader: 如果选举期间candidate收到了心跳并且发现心跳的current term number 至少和自己的current term number一样大则认定leader合法,终止选举并将其状态变为follower;否则拒绝该心跳,仍然保持candidate状态。
  3. 一段时期过去了,没有赢家: 如果每一个candidate都没有拿到特定数量的票数,那么在一定超时时间之后重新开始投票。等待超时时间的原因是server之间网络可能不通。因此发送给某些server的请求得不到应答。另一个原因是前文提及如果RPC调用失败了那么会重试,因此需要等待超时时间。

通过随机的超时时间确保分裂投票很少发生:选举超时时间是在一个固定的时间间隔内随机选择(如150~300ms)。每次选举都会随机的选取一个超时时间。

2.3 日志复制

leader在处理客户端请求的时候步骤如下:

  1. 首先将客户端请求中包含的命令记录到自己的本地日志;
  2. 并行发送AppendEntrics RPC给每一台服务器去复制该日志;
  3. 如果日志被安全复制,则leader将日志应用到复制状态机上,并将结果发送给客户端;
  4. 对于没有出错的RPC调用,leader会一直重试直到所有的follower复制了该日志。

每一个日志都有两个值:term numberlog index

leader同时决定何时将一个日志应用到状态机上;这样的条目叫做committed。一旦一个条目被集群中的大多数服务器复制,则认为该条目被提交;一个条目一旦被创建他的leader提交意味着所有之前的条目都是提交的状态(包括前面的leader创建的条目)。leader追踪其知道的最新被提交的条目的索引,并且将其包含在将来的AppendEntries RPC上(包括心跳)因此其他服务器也会知道最新提交的条目。一旦一个follower知道一个新的条目被提交,那么其将这个条目应用到他的复制状态机上面。

以上的机制保证了:

  • 如果两个不同的日志中的条目有相同的索引,那么他们包含相同的命令;因为leader在特定时期的特定索引上只会创建一个条目,并且条目内容永远不会被改变。
  • 如果两个不同日志中的条目有相同的索引,那么两个日志中所有之前索引的条目都相同。通过AppendEntries RPC一个简单的一致性检查实现:leader会将新条目之前一个条目的term numberindex发送给follower。如果follower发现自己前一个条目的term number和index与leader发送的不同,那么follower会拒绝这个AppendEntries RPC请求。

正常情况下以上机制工作正常,但是当leader宕机的时候,先选出的leader并没有复制之前leader的所有日志的话机会出问题。当有一个新的leader接任时,下图所示的任何情况都会发生:

leader会强制follower的日志与自己的相同来处理这种不一致性。

为了让follower的日志与自己的相同,leader需要找到两个日志中一致的最近的日志条目,删除follow日志中该条目后的所有日志并且将leader从该条条目之后的所有日志发给follower。所有这些动作都是为了响应AppendEntries RPC的一致性检查而发生的。leader为每一个follower维护一个nextIndex变量,其值表示leader向follower发送的下一个日志条目的索引。初始时leader将其设置为自己的log的下一个index;每次检查失败(即follower拒绝了leader的AppendEntries RPC)leader会减少这个值并且重试AppendEntries RPC。最终nextIndex会到达leader和follower相匹配的点,此时AppendEntries RPC成功。一旦AppendEntries RPC成功了则意味着leader和follower的日志是相同的。

可以做一些优化来降低AppendEntries RPC被拒绝的次数。follower在拒绝的同时可以返回冲突的时期和在这个时期其存储的第一个日志条目的索引。leader因此可以绕过当前时期的所有冲突的索引。

需要注意的是,leader从来不会删除或者重写自己的日志。

这种日志复制机制展示了第 2 节中描述的理想共识属性:只要大多数服务器都启动,Raft 就可以接受、复制和应用新的日志条目; 在正常情况下,可以通过一轮 RPC 将新条目复制到集群的大多数; 并且单个慢follower不会影响性能。

2.4 安全性

前述机制并不能保证每个状态机以相同的顺序执行相同的指令exactly once。如果一个落后的follower在新的选举中被选举成为了leader,那么其会重写其他follower的日志导致复制状态机出现不一致性。需要添加如下限制:

2.4.1 选举限制

为了防止缺少log entry的candidate被选举为leader,在follower投票时做了如下的限制:candidate在投票(发送RequestVode RPC)的时候会携带自己的日志信息,如果follower发现自己的日志超过了candidate的日志,那么其将会拒绝对candidate的投票。

日志之间如何进行比较:

  • 如果两个日志的最后一个条目有不同的term number,那么term number大的日志更新;
  • 如果term number相同,则哪个日志更长(index值更大)则更新;
2.4.2 提交之前term的条目

如果当前leader在提交某一条目的过程中宕机了,那么新的leader将会继续尝试提交之前leader未提交的内容。但是新leader在提交之前条目的过程中不能通过该条目是否被大多数follower存储来判断该条目被提交,原因如下:

(a). S 1 S1 S1 是leader,部分复制了条目 ( 2 , 2 ) (2,2) (2,2) 之后宕机;

(b). S 5 S5 S5被选举成为了新的leader

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值