Raft实现报告(五)
一致性检查会做什么
紧接上文为了讲follower的日志与自己保持一致性,leader必须找到最新的日志条目的那个点,且二者的日志都要满足,然后将follower在该点之后的全部的点都删除掉。然后将自己在该点之后的日志全部覆盖到follower的日志中去,简单点来说就是找到二者重合最新的节点处,将leader的日志条目全部覆盖,注意是覆盖follower的日志条目。
全部的这些动作都发生在AppendEntries RPC做一致性检查的时候。leader会位每一个follower维护nextIndex,nextIndex是leader下发下一个log的索引,当leader第一次启动的时候,他会初始化好所有的nextIndex值,紧跟他现有存储的log队列之后。如果follower的日志跟leader的日志不一致,AppendEntriesRPC返回一个拒绝,leader会降低nextIndex的值,然后重新尝试发送RPC请求,最终nextIndex将会到达我们上述的一致点。也就是与不一致follower重合的那个点。
到达同步点之后,ApeendEntries就会成功,因为此时,冲突的条目将会被移除,然后复制leader的条目。一旦AppendEntries成功,那么follower的log将会与leader的保持一致。
raft中可能的优化
如果需要,Raft可以优化,就通过减少AppendEntries RPCs的拒绝次数,举个例子,当follower拒绝了AppendEntries请求,follower可以记录这次冲突发生的term(论文中,raft的逻辑计数器,所记录的是一轮稳定状态的时间段)和这次term中第一个条目索引。带有这些信息的话,leader再去减少nextIndex来绕过所有冲突条目,那每个term中有条目冲突时,AppendEntries都会需要一次,而不是每个条目都需要做一次。在实际体验中,他们还对这种优化的必要性有怀疑,论文中提到失败少有发生,而且不太可能出现有很多不一致的条目的情况。