《深入理解 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 篇!

相关推荐
uzong4 小时前
技术故障复盘模版
后端
GetcharZp4 小时前
基于 Dify + 通义千问的多模态大模型 搭建发票识别 Agent
后端·llm·agent
桦说编程5 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
IT毕设实战小研5 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi5 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
阿华的代码王国6 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
Jimmy6 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
喂完待续7 小时前
Apache Hudi:数据湖的实时革命
大数据·数据仓库·分布式·架构·apache·数据库架构
AntBlack7 小时前
不当韭菜V1.1 :增强能力 ,辅助构建自己的交易规则
后端·python·pyqt
bobz9658 小时前
pip install 已经不再安全
后端