Raft一致性与共识算法 | 豆包MarsCode AI刷题

149 阅读4分钟

Raft这个陌生的词,在一次次讲课与查资料中变得熟悉起来,基本原理说起来并不困难,但是在具体实现的时候还是懵懵懂懂,不甚了解。

1. 引言

维基百科对Raft算法的描述:Raft是一种用于替代Paxos的共识"共识机制")算法。相比于Paxos,Raft的目标是提供更清晰的逻辑分工使得算法本身能被更好地理解,同时它安全性更高,并能提供一些额外的特性。Raft能为在计算机集群之间部署有限状态机提供一种通用方法,并确保集群内的任意节点在某种状态转换上保持一致。

Raft算法的开源实现众多,在Go、C++、Java以及Scala中都有完整的代码实现。Raft这一名字来源于"Reliable, Replicated, Redundant, And Fault-Tolerant"(“可靠、可复制、可冗余、可容错”)的首字母缩写。

2. 关键组件

2.1. 领导者选举

通常领袖会借由固定时间发送消息,也就是”心跳“(heartbeat),让追随者知道集群的领袖还在运作。而每个追随者都会设计超时机制(timeout),当超过一定时间没有收到心跳(通常在150 ms和300 ms之间),集群就会进入选举状态。

Raft每个服务器的timeout是随机的,这是因为避免多个node同时竞选,也降低因两个竞选人得票都不过半而选举失败的几率。

2.2. 日志复制

领袖接收指令,将之写入自己记录中的新指令部分,然后把指令转发给追随者。如果有追随者没反应,领袖会不断重发指令、直到每个追随者都成功将新指令写入记录为止。日志的复制过程如下:

  • 领导者接收客户端请求并将其附加到其日志中,形成日志条目。
  • 然后,领导者将日志条目发送给跟随者(其他节点)以复制数据。
  • 一旦日志条目被复制到一定数量的节点,领导者就会提交该条目并通知追随者将该日志条目应用到他们的状态机。

2.3. 安全

Raft保证以下的安全性:

  • 选举安全性:每个任期最多只能选出一个领袖。
  • 领袖附加性:领袖只会把新指令附加(英语:append)在记录尾端,不会改写或删除已有指令。
  • 记录符合性:如果某个指令在两个记录中的任期和指令序号一样,则保证序号较小的指令也完全一样。
  • 领袖完整性:如果某个指令在某个任期中存储成功,则保证存在于领袖该任期之后的记录中。
  • 状态机安全性:如果某服务器在其状态机上执行了某个指令,其他服务器保证不会在同个状态上执行不同的指令。

前四项保证的原因详见上述领导者选举,状态机安全性则借由下述选举流程的限制所达到。

2.3.1. follower宕机

当某台追随者死机时,所有给它的转发指令和拉票的消息都会因没有回应而失败,此时发送端会持续重送。当这台追随者开机重新加入集群,就会收到这些消息,追随者会重新回应,如果转发的指令已经写入,不会重复写入。

2.3.2. leader宕机

领袖死机或断线时,每个已存储指令必定已经写入到过半的服务器中,此时选举流程会让记录最完整的服务器胜选。其中一个因素是Raft候选人拉票时会揭露自己记录最新一笔的信息,如果服务器自己的记录比较新,就不会投票给候选人。

2.3.3. 超时期限和可用性

因为Raft启动选举是基于超时,使得超时期限的选择至为关键。若遵守算法的时限需求

广播时间 << 超时期限 << 平均故障间隔

就能达到稳定性。这三个时间定义如下:

  • 广播时间 是单一服务器发送消息给集群中每台服务器并得到回应的平均时间,需要测量得到。
  • 超时期限 是发动选举的超时期限,由部署Raft集群的人选定。
  • 平均故障间隔 是服务器发生故障之间的平均时间,可以测量或估计得到。

广播时间典型是 0.5ms 到 20ms,平均故障间隔通常是用周或月来计算的,所以可以将超时期限设在 10ms 到 500ms。