raft算法中,5.4.2节一疑问( 三 )


问题:
如果leader(currentTerm=term1)可以直接提交term\u0026lt;term1的entry,那么可能导致已经commit的entry被重写。
说明:
按照上面的条件,(c)中term为2的entry被集群中大多数的服务器存储,此时可以commit(也就是leader的commitIndex加一)。随后,该entry加入到状态机中(leader的lastApplied加一)。接着,S1宕机,整个集群里面只有S2,S3,S4和S5。因为S5日志“最新”(log中有两个entry并且最后一个entry的Term为3),被选为leader(currentTerm为5),继续复制index为2(term为3)的entry,将S5的log复制到集群中的每个服务器。最后,已经commit的entry(term为2),被重写为了term为3的entry。
方法:
不允许leader(currentTerm=term2),提交term\u0026lt;term2的entry,只允许提交term=term2的entry。
说明:
对于(e),term为2的entry没有被提交。当leader(currentTerm=4)发现,term为4的entry被大多数服务器存储,那么可以提交term为4的entry,并同时提交term为2的entry(根据 Log Matching Property,集群中大多数服务器的log已经和leader一致,term2的entry也被存储在大多数服务器中)。
Log Matching Property:
如果两个log entry有相同的index和term,那么它们存储相同的指令如果两个log entry在两份不同的日志中,并且有相同的index和term,那么它们之前的log entry是完全相同的
■网友
因为raft中,log才是实实在在的东西,term只是一个逻辑时间。
没有写入日志就说明根基不稳,随时都可能被干掉。
只有写入日志了才算正式就职,
只拿到选票是不能保证的,因为下属可能改换门庭,选票都是虚的。
因为下属选了你也可以选别人,只能算口服,其他人来拉选票还是可以投其他人的。
只有写入了log,才算心腹,此时没有这条log的其他人会被拒绝。
既然你还不是是leader,就不能进行提交。

If RPC request or response contains term T \u0026gt; currentTerm: set currentTerm = T, convert to follower如果写入日志时出现这种情况,A会默默的下台。

■网友
照我的理解:
就是按5.4.2中说的不主动单独提交不是当前 term 的日志, 之前 term 的日志通过提交当前 term 的日志一起提交, 也就是说不会出现图 c 中的情况(因为如果term2的日志提交了, 按照规则限制,那么4的日志一定也提交了.), 只会出现 d/e 中的一种.
■网友
根据原来的规则,确实会存在d、e两种情况,为了解决这个问题,引入了一个新的规则。1、commited的条目必须存在大多数机器上。2、leader 任期内新增的条目必须存在多数机器上。 所以,在这种情况下,根据leader的选举规则(1、candidate的任期号必须大于投票机器上的最大任期号,或者日志条目的索引号大于投票机器的日志索引号。 2、candidate 日志条目必须比投票机器全。),s5根本没有机会成为新的leader 。所以,最终的状态是e,而不是d. (参考https://www.bilibili.com/video/av35310245/ 第36:50s的介绍)

■网友
刚刚看到这里,说一下自己的理解
(c)中的S1在term 4确立自己的领导,并且收到了term 4中需要处理的日志(索引为3的位置),依据Log Matching,可能会出现(c)中的情况,如果不发生故障,继续处理,对应的是(e),提交term 4内的日志,此时日志1-2-3都是committed
(d)对应的是S1再度出现故障,S5取得控制权,此时的term至少是5,但是没有收到新的需要处理的日志,而term 2索引为2的日志,虽然已经被多数节点记录,但是不会被算作committed,通过心跳包(空的AppendEntries RPC),follower会执行一致性检测,出现图中所示的情况,但是此时term 为3,索引为2的日志依然不能算作是committed


推荐阅读