关于 TiKV proposal apply 的一点疑问

TiKV 源码解析系列文章(十八)Raft Propose 的 Commit 和 Apply 情景分析 这篇文章末尾有如下一段描述:

这里存在一个特殊情况,就是所谓的“空日志”。在 raft-rs 的实现中,当选举出新的 Leader 时,新 Leader 会广播一条“空日志”,以提交前面 term 中的日志(详情请见 Raft 论文)。此时,可能还有一些在前面 term 中提出的 proposal 仍然处于 pending 阶段,而因为有新 Leader 产生,这些 proposal 永远不可能被确认了,因此我们需要对它们进行清理,以免关联的 callback无法调用导致一些资源无法释放。清理的逻辑参照 ApplyFsm::handle_entries_normal函数。

这里提到 —— “可能还有一些在前面 term 中提出的 proposal 仍然处于 pending 阶段,而因为有新 Leader 产生,这些 proposal 永远不可能被确认了” ,我的疑问是这些 proposal 不应该是在这个 leader 上一次 lost leadershipt 的时候就清理掉直接返回 StaleCommand 错误,而是要等到再次当选 leader 了才清理?

清理应该是选举完成之后,log 数据对齐的过程

proposal 不被确认,如果提交没超过半数,提交就失败了,也可以保证一致性

A(leader) [ 1 2 3 4] B [1 2 3 ] C [1 2 3 ]
这时候发生了选举,C当选了
A[ 1 2 3 4] B [ 1 2 3 ] C (leader)[1 2 3]
C要应用一条空日志
A[1 2 3 4] B [1 2 3 5] C(leader)[1 2 3 5)
这时候,A也收到了5,就直接把4删掉了。
最终就是
A[1 2 3 5] B [1 2 3 5] C(leader)[1 2 3 5]

1 个赞

我的理解是 C 给 A 发的第一条 AppendEntries 请求 term 是 5,这时候 A 就知道已经 lost leadership,就应该把本地的 proposal 全部清掉并返回 stale command 了

在知道 lost leadership 的情况下为什么还要等数据对齐,直接清理设计上不是更简单清晰吗?

我上面举例子的12345,是log的index,第一条空日志就是5。