RAFT 论文——村委会版
2026/9/19 7:38:59 网站建设 项目流程

RAFT 论文——村委会版

写给完全忘记 RAFT 的自己。读完这篇,等于把论文学了一遍。


登场角色

村委会里的人/物论文里叫什么
村长Leader(领导者)
委员Follower(跟随者)
正在竞选的委员Candidate(候选人)
小张(来办事的村民)Client(客户端)
记录本Log(日志)
记录本里的一条Log Entry(日志条目)
村长盖章生效Committed(已提交)
本届任期编号Term
村长定期打招呼Heartbeat(心跳)
村长同步记录的消息AppendEntries RPC
候选人拉票的消息RequestVote RPC
发快照的消息InstallSnapshot RPC
小张给消息贴的编号Session ID(流水号)

第一章:RAFT 是什么

想象一个村委会,有 1 个村长、4 个委员,共 5 人。

村里所有决定——批地、盖房、开店——都要记在记录本里。

问题是:这 5 个人每人手里有一本,怎么保证 5 本始终一样?万一村长突然晕倒,怎么办?

RAFT 就是解决这个问题的方法。

核心思路三句话:

  1. 所有写入都经过村长,村长说了算
  2. 超过半数的人记下来,才算正式生效
  3. 记录最全的人才有资格当村长

第二章:正常运转——日志复制

小张来申请建新房

第一步:小张找到村长

小张只能找村长办事,不能找委员。

村长在自己的记录本上写下:

第88条:批准小张建房(未盖章)

第二步:村长通知所有委员

村长给 4 个委员发消息(AppendEntries RPC):

“大家在第88条写上:批准小张建房”

第三步:超过半数回复"已记"

委员回复
委员A✅ 已记
委员B✅ 已记
委员C❌ 没反应(在睡觉)
委员D✅ 已记

5 人里 4 人写好了,超过半数 → 可以生效。

第四步:村长盖章,通知大家也盖章

村长在自己本子上盖章(Commit),通知委员们也盖章,再告诉小张:“批了!”

那个睡觉的委员C呢?

不用管他。村长下次发消息时顺带把他落下的条目补给他,他自己追上来。


关键原则

超过半数写好就算数,不需要所有人都确认。

5 人村:3 人确认就够。
7 人村:4 人确认就够。


第三章:村长失联——领导者选举

村长定期"打招呼"

正常情况下,村长每隔一小段时间给所有委员发一条空消息(Heartbeat),意思是"我还在,别慌"。

委员们收到后重置自己心里的倒计时。

村长突然失联

委员们停止收到心跳,各自的倒计时开始走。

倒计时是随机的,150 到 300 毫秒之间,每个人不一样。

为什么随机?防止大家同时举手、同时拉票,谁也选不上。

先数完的人举手拉票

委员B的倒计时先到 → 升级为Candidate→ 把任期编号(Term)加一 → 给所有人发消息(RequestVote RPC):

“村长失联了!我要竞选,请投我一票!”

其他委员怎么投票?

两个条件都满足才投:

条件说明
这轮没投过票每轮每人只能投一票
候选人记录本不比我旧记录落后的人没资格当村长

两个都满足 → 投票。任意一个不满足 → 拒绝。

当选

委员B收到超过半数的票 → 当选村长 → 立刻发心跳,告诉大家"我是新村长"。

平票或没人过半怎么办?

这轮作废,所有人重新随机倒数,再来一轮。

会不会永远选不出来?极低概率。每次碰撞都要求大家倒计时恰好一样长,连续碰撞的概率像连续中彩票,实际上几乎不发生。


第四章:新村长上任——记录怎么保持正确

为什么新村长记录一定最新?

选举时,候选人要"亮记录本"——通过 RequestVote RPC 告诉大家自己的最后一条记录编号。

委员的规则:你的记录比我旧,我不投你。

所以记录落后的候选人拿不到多数票,天然被淘汰。当选的人必然是记录最新的。

新村长上任后做什么?

把自己记录本里还没盖章的条目继续同步给所有委员,重新走一遍"超过半数确认 → 盖章"的流程,把之前没完成的事情收尾。


第五章:小张怎么找村长

正常情况

小张直接找村长办事。

村长挂了,小张不知道新村长是谁

小张随机挑一个委员去问。委员会拒绝办理,但告诉小张:

“我不是村长,去找B,他是新村长。”

委员通过收到的心跳消息知道谁是现任村长(AppendEntries RPC 里附带村长地址)。

选举还没结束,委员也不知道新村长是谁

委员无法提供地址,小张的请求超时,没有回应。

小张随机换一个委员再问,不是反复问同一个人。

选举通常在 150~300 毫秒内结束,多问几次就能得到答案。


第六章:村子要加人减人——集群成员变更

为什么不能直接换名单?

原来 5 人,加 2 人变 7 人。

如果消息发出去,有人早收到、有人晚收到,可能同一时刻:

  • 用旧名单(5人)的人:3票过半 → 选出村长甲
  • 用新名单(7人)的人:4票过半 → 选出村长乙

两个村长同时存在,记录本就乱了。

解法:联合共识(Joint Consensus)——过渡期

村长不发"换成新名单",而是发一张过渡公告,同时写着新旧两份名单:

过渡公告:
旧名单:A B C D E
新名单:A B C D E F G
收到此公告的人,两份名单都要用

过渡期投票规则:一票同时计入两份名单,两边都要超过半数才算通过。

为什么这样就安全了?(鸽巢原理)

用旧规则选出的村长:必须拿到旧名单里的多数(≥3票)
用新旧双规则选出的村长:也必须拿到旧名单里的多数(≥3票)

两边合计需要至少 3+3=6 票,但旧名单只有 5 个人,每人只有一票,6>5,票不够分。

结论:两个"多数派"必然重叠,不可能同时存在两个合法村长。

过渡期结束

村长确认过渡公告被多数人收到后,发第二份公告,切换到纯新名单。过渡期通常只持续几百毫秒。


第七章:记录本太长怎么办——快照

问题

村子运行 3 年,记录本写了 10 万条。新来的委员 F 要从头抄,抄到什么时候?

解法:定期拍快照(Snapshot)

每隔一段时间,把前面所有记录压缩成一张现状表

村民当前状态
小张已批建房
小李已批开店
小王申请中

这张表代替了前面所有记录,旧记录直接删掉。

快照里还要记两个数字:

  • 压缩到第几条(比如第400条)
  • 那条记录的任期编号

用来告诉别人"从第401条开始接着抄"。

每个委员自己决定拍快照的时机

不需要村长统一指挥,记录本超过一定大小就自己拍。

新委员落后太多怎么办?

村长通过InstallSnapshot RPC把快照切成小块发给委员 F:

村长 → F:第1块(共10块) 村长 → F:第2块 ... 村长 → F:第10块,发完了

F 收齐后整体替换自己的记录本,从快照最后一条编号接着同步新记录。

收到一半村长挂了?F 把收到的块存在草稿里,没收齐不替换正式记录本,新村长上任后重新发一遍。


第八章:小张重复发消息怎么办——线性化语义

问题

  1. 小张发"批准建房"
  2. 村长处理了,盖章生效
  3. 村长回复的消息路上丢了
  4. 小张没收到,再发一次
  5. 会不会被批两次?

解法:流水号(Session ID)

小张给每条消息贴唯一编号:

消息#001:批准建房

村长处理完,把"#001已处理"记在本子上。

下次再收到"消息#001",查一下,发现处理过了,直接回放上次结果,不重新执行

村长换人了也没事——流水号记录随日志同步,新村长也知道哪些已处理。

论文把这叫做Linearizability(线性化语义):每条操作恰好执行一次,不多不少。


第九章:三条铁律——安全性保证

铁律含义村委会说法
Election Safety每个 Term 最多只有一个 Leader同一届任期只能有一个村长
Leader Completeness已提交的条目未来所有 Leader 都有盖了章的记录永远不消失
State Machine Safety所有节点在同一编号位置执行的命令相同所有记录本在同一行写的内容完全一样

最后一句话

强领导者统一写入,随机超时避免选举冲突,多数派确认保证持久,记录越新越有资格当选——四点合在一起,让分布式系统的记录本永远不乱。


基于 RAFT 论文(In Search of an Understandable Consensus Algorithm,Diego Ongaro & John Ousterhout)整理

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询