今天面试被问到一个问题: raft在当前任期内能够commit之前任期中已经复制给大多数节点但没有commit的日志条目吗?

我当时没答上来, 之后查看了下raft作者的博士论文, 发现3.6.2节就是讨论了这个问题. 之前学raft的时候, 都是看的另一篇ATC2014的论文, 没有看博士论文, 所以没看到这个点. 所以学习时偷的懒, 在面试的时候就暴露出来了.

结论是: 当前term的leader是可以提交之前term的日志的.

PS. 有的文章把这个叫做 “当前term的leader不能提交之前term的日志, 只能提交本term的日志”, 但是我觉得间接提交也算是提交吧, 只不过提交方式和当前term的日志不同, 但也算是提交了.

当时面试官的说法也是这种.

不过说法不一样, 但实际代表的含义是一样的, 我觉得这两种表述都有道理吧.

毕竟这一节就叫做 “3.6.2 Committing entries from previous terms”.

不过和当前任期的节点是通过判断日志被复制到大多数节点后就可以进行commit的方式不同, 对于之前term的日志, 只能通过在提交当前term的日志的同时, 间接地使用日志匹配特性将之前term中未提交的日志进行提交, 而不能通过计算之前term的日志已经被复制到大多数节点上从而进行commit. 当然, 前提是这个日志已经复制在当前leader中, 否则leader不会承认这个日志(且会覆盖掉).

论文中通过下图表示的例子来解释为什么

image-20220301211326350

图 3.7:如图的时间序列展示了为什么领导者无法决定对老任期号的日志条目进行提交。

在 (a) 中,S1 是领导者,部分的复制了索引位置 2 的日志条目。

在 (b) 中,S1 崩溃了,然后 S5 在任期 3 里通过 S3、S4 和自己的选票赢得选举,然后从客户端接收了一条不一样的日志条目放在了索引 2 处。

然后到 (c),S5 又崩溃了;S1 重新启动,选举成功,开始复制日志。在这时,来自任期 2 的那条日志已经被复制到了集群中的大多数机器上,但是还没有被提交。

如果 S1 在 (d1) 中又崩溃了,S5 可以重新被选举成功(通过来自 S2,S3 和 S4 的选票),然后覆盖了他们在索引 2 处的日志

反之,如果在崩溃之前,S1 把自己主导的新任期里产生的日志条目复制到了大多数机器上, 就如 (d2) 中那样,那么在后面任期里面这些新的日志条目就会被提交(因为 S5 就不可能选举成功)。 这样在同一时刻就同时保证了,之前的所有老的日志条目就会被提交。

这种情况说明, 即使之前某任期的日志被复制到大多数节点, 也可能被覆盖掉;

为了消除图 3.7 里描述的情况,Raft 永远不会通过计算副本数目的方式去提交一个之前任期内的日志条目。只有领导者当前任期里的日志条目通过计算副本数目可以被提交;**一旦当前任期的日志条目以这种方式被提交,那么由于日志匹配特性,之前的日志条目也都会被间接的提交。**在某些情况下,领导者可以安全的知道一个老的日志条目是否已经被提交(例如,该条目是否存储到所有服务器上),但是 Raft 为了简化问题使用一种更加保守的方法。

参考资料:

  1. raft作者博士论文
  2. https://blog.csdn.net/weixin_44969471/article/details/106607359