← 返回题目列表

commitIndex 和 appliedIndex 有什么区别?

中等 第 17 / 26 题 更新于 2026/09/30
commitIndexappliedIndexRaft状态机
学习 AI 实战项目

简化版

commitIndex 表示已经被共识协议确认、不会被未来 Leader 覆盖的最高日志索引;appliedIndex 表示本节点已经把日志执行到状态机的最高索引。 必须满足 appliedIndex 不大于 commitIndex,正常情况下 appliedIndex 会追赶 commitIndex。 两者差距大说明共识已完成但业务状态机执行慢,线性一致读必须等应用到安全读取索引。

详细版

Leader 将日志复制到多数派后推进 commitIndex,并把提交边界通知 Follower。 各节点按日志顺序把已提交条目应用到状态机,再推进 appliedIndex。 提交是协议层结论,应用是本地执行进度;它们不是同一原子时刻。

若 commitIndex=1000、appliedIndex=940,本节点还有 60 条确定的命令未执行。 此时不能用状态机回答要求覆盖索引 1000 的读,也不能仅凭 lastLogIndex 宣称已恢复。 监控 commit-applied gap、应用耗时和快照进度,状态机执行必须确定、顺序且可恢复。

完整版教学

一、先看三个常见索引

lastLogIndex 是本地最后一条已持久化日志。 commitIndex 是已确认提交的最大索引。 appliedIndex 是已执行到状态机的最大索引。

日志“收到”“提交”“执行”是三个阶段,任何两个都不能混为一谈。

二、正常推进流程

append local log
-> replicate to quorum
-> advance commitIndex
-> apply entries in order
-> advance appliedIndex

Follower 可先收到日志但尚未知道它已提交。 Leader 后续通过 AppendEntries 携带 leaderCommit,Follower 才更新提交边界。

三、必须满足的不变量

通常有 appliedIndex <= commitIndex <= lastLogIndex。 状态机严格按索引递增应用,不跳过条目。 已提交条目在后续合法 Leader 中必须保留。 节点重启后从持久化 applied 边界或快照继续,不能把同一非幂等副作用随意执行两次。

四、差距说明什么

现象可能原因
lastLog 落后 commit复制、网络或磁盘慢
commit 追平但 applied 落后状态机、IO、大命令慢
applied 长期不动apply 线程卡死或坏条目
快照 index 高于日志起点已完成日志压缩

1000 与 940 的 60 条差距要结合每条执行成本和时间判断。

五、读取为何关心 appliedIndex

ReadIndex=1000 只表明该读必须观察到索引 1000 前的提交。 若本地状态机只应用到 940,立即读取会返回旧值。 因此执行节点等待 appliedIndex 至少达到 readIndex。 Follower read 也遵守同一条件,不能只比较 matchIndex。

六、快照与恢复

快照包含状态机在 lastIncludedIndex 时的状态和对应 term。 安装成功后 appliedIndex 至少推进到该索引,旧日志可被裁剪。 快照写入必须与应用边界一致,不能捕获半条命令效果。 恢复时先加载完整快照,再重放其后的已提交日志。

七、观测和背压

监控 gap 条数、字节、秒数、单条 apply 延迟和最老未应用日志年龄。 若 apply 长期跟不上提交,继续无限接收写会扩大内存、磁盘与恢复时间。 系统可限制大命令、分离慢副作用或在 gap 达阈值时背压写入。 外部副作用应通过幂等 outbox 等模型处理,避免状态机重放不可控调用。

八、常见误区与追问

  • 误区:日志复制到本地就能执行。 只有已提交条目才能进入状态机。
  • 误区:commitIndex 推进代表查询立刻可见。 还要等待 appliedIndex。
  • 误区:lastLogIndex 相同就代表副本状态相同。 应用进度仍可能不同。
  • 误区:状态机可以并行乱序应用。 除非实现证明无冲突,否则会破坏确定性顺序。
  • 追问:apply 慢会影响共识安全吗? 通常不破坏日志安全,但影响读新鲜度、内存和可用性。
  • 追问:重启会重复应用吗? 取决于持久化边界;状态机恢复设计必须避免重复副作用。
  • 追问:快照索引是什么? 快照已包含状态机效果的最后日志索引。

九、加强记忆

  1. lastLog 是收到,commit 是协议确认,applied 是状态机执行。
  2. applied 不得超过 commit。
  3. 线性一致读等待应用到安全索引。
  4. commit-applied gap 定位状态机瓶颈。
  5. 快照和重启必须准确保存应用边界。