news 2026/9/5 4:38:24

RAFT 实现难点——论文没告诉你的那些事

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
RAFT 实现难点——论文没告诉你的那些事

RAFT 实现难点——论文没告诉你的那些事

论文描述的是"晴天"下的规则。代码要处理的是任意时刻的崩溃、丢包、延迟和分区——任意组合,同时发生。


核心矛盾

论文说的是理想流程,实现要处理的是意外

两者的差距就是 RAFT 实现难的地方。


六类典型边界情况

1. 老村长回来了(过期 Leader)

场景:Leader A 因网络断开被判定失联,B 当选新 Leader。A 的网络恢复后,它还以为自己是 Leader,继续发指令。

难点:A 和 B 同时发指令,记录本乱套。

正确处理:每条消息带 Term 编号。A 收到 B 的消息,发现 B 的 Term 比自己大,必须立刻承认下台,降回 Follower。

漏实现的后果:两个 Leader 同时写入,数据不一致。


2. 盖章盖到一半,Leader 挂了(上一任的未提交记录)

场景:Leader 把第88条同步给了 A、B,但还没通知 C、D 就挂了。新 Leader 上任,第88条在部分节点上存在。

难点:新 Leader 能不能直接把第88条算作已提交?

论文里最微妙的规定:

新 Leader 不能直接提交上一任 Term 的记录,必须先提交一条自己 Term 的新记录,才能间接让旧记录生效。

为什么?防止一种极端场景:旧记录在新 Leader 上提交,但实际上之前已经被另一个 Leader 覆盖过。

漏实现的后果:已"提交"的记录后来被覆盖,违反 Leader Completeness 铁律。


3. 幽灵消息(过期 RPC)

场景:Candidate C 发出拉票消息,但网络延迟,消息绕了一大圈才到。这期间 B 已当选,Term 从 2 变成了 3。C 的消息带的还是 Term 2。

难点:过期消息干扰已稳定的新任期。

正确处理:收到 Term 比自己小的消息,直接无视,不做任何处理,不回复。

漏实现的后果:旧消息触发不该发生的状态转换,选举结果被破坏。


4. 投票记录不能丢(持久化顺序)

场景:Follower 投票给 B 后,立刻崩溃重启。重启后它还记得自己投过吗?

难点:如果不记得,同一轮可能投两票,破坏"每人每轮只投一票"的保证。

正确处理:投票记录必须在回复投票消息之前写入磁盘(持久化)。

顺序至关重要:

❌ 错误:先发回复 → 再写盘 → 崩溃 → 重启后不记得投过 ✅ 正确:先写盘 → 再发回复 → 崩溃 → 重启后知道投过

同样需要持久化的状态:当前 Term、投票给谁、已接受的 Log。

漏实现的后果:同一轮出现两个合法 Leader。


5. 网络分区(脑裂)

场景:集群被切成两半,东边 3 人(含 Leader)、西边 2 人。西边等了一会儿,选出了新 Leader。大雪过去,两边重新联通。

难点:两个 Leader 在分区期间各自写了不同的记录,恢复后谁的算数?

正确处理:

  • 西边 2 人凑不够多数(5人村需要3票),实际上什么都没提交
  • 东边 3 人可以正常提交,Term 更大
  • 恢复联通后,西边 Leader 收到东边更大的 Term,立刻降为 Follower,回滚自己多写的未提交记录

漏实现的后果:分区期间西边写入的记录被当作已提交,恢复后数据冲突。


6. 并发与竞态(共享状态)

场景:同时收到心跳、拉票请求、客户端请求,多个 goroutine(或线程)同时修改 Term、Log、投票状态。

难点:状态更新不是原子的,并发修改导致不一致。

典型竞态:

  • 检查 Term 和修改 Term 之间插入了另一个操作
  • 发送 RPC 期间状态已经改变,回调处理旧结果

正确处理:对共享状态加锁,且锁的粒度要合适——太粗会死锁,太细会漏保护。


必须持久化的三样东西

状态原因
当前 Term重启后不能用旧 Term 参与投票,否则破坏选举唯一性
投给了谁(votedFor)防止同一轮投两票
Log 条目已接受的记录重启后不能丢

其余状态(commitIndex、角色等)重启后可以重新推导,不需要持久化。


实现难度总结

意外类型核心难点
消息丢失重试幂等性,流水号去重
消息乱序/延迟Term 编号过滤过期消息
崩溃重启持久化顺序(先写盘再回复)
网络分区/脑裂分区恢复后未提交记录的回滚
并发共享状态加锁,RPC 回调检查状态是否过期
Leader 交接新 Leader 不能直接提交上一任的记录

每一条单独看都不难。它们可以任意组合同时发生——这才是 RAFT 实现难的地方。


一句话

论文给了你规则,实现要你在规则的每一个缝隙里,堵住所有可能出错的时机。


配合《RAFT 论文——村委会版》一起读效果最佳

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/5 4:37:37

大一暑假嵌入式入门:从抄板到打样焊接的完整路线

大一暑假,如果你正捧着手机刷到“嵌入式硬件”这几个字,心里又好奇又没底,那我先给你一句定心话:这条路完全可以在一个暑假里走通,而且最粗暴的第一步,不是抱着《模拟电子技术》啃,而是跟着视频…

作者头像 李华
网站建设 2026/9/5 4:37:34

Unity飞行控制器实现指南:物理、状态与手感调优

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/5 4:34:43

学完STM32还是找不到工作?嵌入式开发从点灯到工程化的关键跨越

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/5 4:24:10

AI Agent开发实战:从插件生态到生产部署的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/5 4:22:16

亲子一日游好去处,三亚槟榔谷别错过

在三亚,有一处能让孩子们亲近自然、了解少数民族文化的绝佳之地——槟榔谷。这里不仅风景秀丽,还充满了浓郁的民族风情,是亲子一日游的不二之选。一、丰富多样的民族文化体验槟榔谷景区坐落于万余棵婀娜多姿、亭亭玉立的槟榔林海中&#xff0…

作者头像 李华