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 论文——村委会版》一起读效果最佳
上一篇/下一篇内容由系统自动关联
返回资讯列表 →