Raft共识算法在分布式系统中是常用的共识算法之一,论文原文In Search of an Understandable Consensus Algorithm ,作者在论文中指出Poxas共识算法的两大问题,其一是难懂,其二是应用到实际系统存在困难。针对Paxos存在的问题,作者的目的是提出一个易懂的共识算法,论文中有Designing for understandability单独一小节,其中强调Raft必须是一个实用的、安全可用、有效易懂的共识算法。本文描述了Raft共识算法的细节,很多内容描述及引用图片均摘自论文原文。
Raft概述我们主要分以下三部分对Raft进行讨论:
Leader election——a new leader must be chosen when
an existing leader fails. (领导人选举)
Log replication——the leader must accept log entries from clients and replicate them across the cluster,
forcing the other logs to agree with its own.(日志复制)
Safety——the key safety property for Raft. (安全性)
正常工作过程中,Raft分为两部分,首先是leader选举过程,然后在选举出来的leader基础上进行正常操作,比如日志复制操作等。
一个Raft集群通常包含\(2N+1\)个服务器,允许系统有\(N\)个故障服务器。每个服务器处于3个状态之一:leader、follower或candidate。正常操作状态下,仅有一个leader,其他的服务器均为follower。follower是被动的,不会对自身发出的请求而是对来自leader和candidate的请求做出响应。leader处理所有的client请求(若client联系follower,则该follower将转发给leader)。candidate状态用来选举leader。状态转换如下图所示:
为了进行领导人选举和日志复制等,需要服务器节点存储如下状态信息:
状态 所有服务器上持久存在的currentTerm 服务器最后一次知道的任期号(初始化为 0,持续递增)
votedFor 在当前获得选票的候选人的 Id
log[] 日志条目集;每一个条目包含一个用户状态机执行的指令,和收到时的任期号
状态 所有服务器上经常变的
commitIndex 已知的最大的已经被提交的日志条目的索引值
lastApplied 最后被应用到状态机的日志条目索引值(初始化为 0,持续递增)
状态 在领导人里经常改变的 (选举后重新初始化)
nextIndex[] 对于每一个服务器,需要发送给他的下一个日志条目的索引值(初始化为领导人最后索引值加一)
matchIndex[] 对于每一个服务器,已经复制给他的日志的最高索引值
Raft在任何时刻都满足如下特性:
Election Safety:在一个任期中只能有一个leader;
Leader Append-Only:leader不会覆盖或删除日志中的entry,只有添加entry(follower存在依据leader回滚日志的情况);
Log Matching:如果两个日志包含了一条具有相同index和term的entry,那么这两个日志在这个index之前的所有entry都相同;
Leader Completeness: 如果在某一任期一条entry被提交committed了,那么在更高任期的leader中这条entry一定存在;
State Machine Safety:如果一个节点将一条entry应用到状态机中,那么任何节点也不会再次将该index的entry应用到状态机里;
下面我们详细讨论这几部分。
Leader选举(Leader election)一个节点初始状态为follower,当follower在选举超时时间内未收到leader的心跳消息,则转换为candidate状态。为了避免选举冲突,这个超时时间是一个随机数(一般为150~300ms)。超时成为candidate后,向其他节点发出RequestVoteRPC请求,假设有\(2N+1\)个节点,收到\(N+1\)个节点以上的同意回应,即被选举为leader节点,开始下一阶段的工作。如果在选举期间接收到eader发来的心跳信息,则candidate转为follower状态。
在选举期间,可能会出现多个candidate的情况,可能在一轮选举过程中都没有收到多数的同意票,此时再次随机超时,进入第二轮选举过程,直至选出leader或着重新收到leader心跳信息,转为follower状态。
正常状态下,leader会不断的广播心跳信息,follower收到leader的心跳信息后会重置超时。当leader崩溃或者出现异常离线,此时网络中follower节点接收不到心跳信息,超时再次进入选举流程,选举出一个leader。
这里还有补充一些细节,每个leader可以理解为都是有自己的任期(term)的,每一期起始于选举阶段,直到因节点失效等原因任期结束。每一期选举期间,每个follower节点只能投票一次。图中t3可能是因为没有获得超半数票等造成选举失败,须进行下一轮选举,此时follower可以再次对最先到达的candidate发出的RequestVote请求投票(先到先得)。