《深入理解 Nacos 集群与 Raft 协议》系列三:日志对比机制:Raft 如何防止数据丢失与错误选主

《深入理解 Nacos 集群与 Raft 协议》系列

大家好,我是G探险者!

在第 2 篇中,我们讲解了 Raft 的选主过程。但单靠"投票数过半"并不能完全保障新 Leader 的安全性。

为了防止数据丢失和不合法的 Leader 被选出,Raft 引入了关键的 日志对比机制(Log Comparison)。这一机制确保:

只有拥有"最新日志"的节点才能当选 Leader。

那么,"最新"是如何判断的?这个机制是如何工作的?又是如何保障数据一致性的?我们逐一解析。


一、为什么投票不能只看任期?

设想一个场景:

  • 第 1 次提交时,A 是 Leader,ABC 同步成功
  • A 崩溃后,CDE 成为候选人集群
  • D 发起选主,但 D 的日志落后于之前提交的日志

如果这时 D 被选为 Leader,就会出现:

  • D 发起的 AppendEntries 会让 C 删除与其不同的日志项
  • 导致之前提交的日志被回滚,数据丢失!

这就是 "旧节点错误地成为 Leader" 导致的严重后果。

Raft 设计了日志对比机制来彻底避免这种情况。


二、日志对比的两个关键字段

当 Candidate 发起选举时,会在 RequestVote 请求中附带:

text 复制代码
lastLogIndex:最后一条日志的索引
lastLogTerm:最后一条日志的任期号

Follower 收到投票请求时,会进行判断:

候选人的日志是否"更新"?

判断规则如下:

  1. 谁的 lastLogTerm 大,谁的日志更新
  2. 如果 lastLogTerm 相同,则看 lastLogIndex 谁大

只有候选人日志"更新"时,Follower 才会投票。


三、为什么这样判断就足够安全?

这种机制保证了:

  • 所有当选的 Leader,日志一定不比大多数节点旧
  • 从而不会覆盖大多数节点上已经存在的日志

换句话说,新 Leader 必须包含"前任 Leader 已提交的日志"

这就实现了我们在第 1 篇中提到的:"每次提交的多数派之间必须有交集",从而实现日志递进一致性。


四、举个例子来理解日志对比

假设 5 个节点:A、B、C、D、E

  • A 是 Leader,提交了 index=3 的日志
  • 复制到了 ABC 节点

这时 A、B 宕机,C、D、E 存活。

  • D 发起选举,日志只到 index=1(旧)
  • C 拒绝投票,因为自己的 lastLogTerm/index 更新

→ D 选举失败,不能成为 Leader

接下来 C 发起选举,D、E 都投票 → 成功成为新 Leader

因为 C 拥有最完整的日志,才有资格成为 Leader。


五、Raft 如何保证最终一致性?

有了日志对比机制,Raft 能做到:

  • 选主只选"最新"的节点,防止数据倒退
  • 新 Leader 会用自己的日志覆盖旧节点的非一致日志
  • AppendEntries 中包含前一个日志的索引和任期,作为对齐基准

最终,每个节点的日志都会逐步和 Leader 保持一致。


六、在 Nacos 中的体现

你可以从以下场景中感受到日志对比的存在:

  • 节点日志落后,迟迟不能当选 Leader
  • 选主期间频繁看到日志校验失败的投票日志
  • 某节点刚启动,必须通过日志对齐后才成为稳定成员

这些机制背后,都是为了实现一致性的日志对比与对齐。


七、总结

Raft 的日志对比机制,是保障"选主安全性"和"日志最终一致性"的核心:

  • 投票时检查候选人日志是否比自己新
  • 防止日志回滚,避免脑裂与数据丢失
  • 所有新 Leader 都必须有前任 Leader 的提交副本

下一篇我们将继续讲解:

💡 Raft 日志是如何复制的?提交策略、确认机制与幂等性保障

敬请期待第 4 篇!

相关推荐
一灯架构4 小时前
90%的人答错!一文带你彻底搞懂ArrayList
java·后端
mldong5 小时前
Python开发者狂喜!200+课时FastAPI全栈实战合集,10大模块持续更新中🔥
后端
不懂的浪漫5 小时前
mqtt-plus 架构解析(六):多 Broker 管理,如何让一个应用同时连接多个 MQTT 服务
spring boot·分布式·物联网·mqtt·架构
GreenTea6 小时前
从 Claw-Code 看 AI 驱动的大型项目开发:2 人 + 10 个自治 Agent 如何产出 48K 行 Rust 代码
前端·人工智能·后端
Moment8 小时前
AI 全栈指南:NestJs 中的 Service Provider 和 Module
前端·后端·面试
IT_陈寒8 小时前
为什么我的JavaScript异步回调总是乱序执行?
前端·人工智能·后端
Moment8 小时前
AI全栈入门指南:NestJs 中的 DTO 和数据校验
前端·后端·面试
小村儿8 小时前
Harness Engineering:为什么你用 AI 越用越累?
前端·后端·ai编程
小码哥_常9 小时前
为什么PUT和DELETE请求在大公司中逐渐被弃用?
后端
宫_商_角_徵9 小时前
动态代理到底在做什么?
后端