Raft的每个实例维护着一个nextIndex数组,这个数组在leader状态使用。

记录每一个follower下一个应该放置的log的下标

leader发送的第一个AppendEntriesRPC往往是一个空的包(不包含日志数据的心跳包,大部分时候是空的,如果当选leader和发送AppendEntries之间leader接收了新的数据,那么这部分新数据也会发送)。

其他实例在收到AppendEntries后,

首先判断term是否>=自身term,如果是的话,那么就意识到有新的leader产生。

接着从RPC request参数里判断日志数据是否冲突,当前已提交的log index等,然后更新本地的Logs和commitIndex。

具体怎么做的,看下AppendEntries RPC的参数及实现

term
leaderId 用于follower记录leader的信息,指示是否已有leader
prevLogIndex 即nextIndex-1,当前已经存储的最新index,用来解决是从哪里开始复制
prevLogTerm
entries[] // empty for heartbeat
leaderCommit // leader’s commitIndex

判断:
如果接受者term更大,拒绝接受日志
如果发送者term更大,更新自身term,votedfor重置为-1;
因为votedfor记录了上一次投给谁了,而且requestvote阶段会对结果产生影响,别人term更大,证明有新的已经产生了,我记录的不可信了。

如果term相等,自身的index和leader认为应该具有的logindex做比较。如果自身小于等于应该有的,说明不足应该补足,但不知道从哪补,要找;如果自身的更多,那么不知道谁的更新,应该比term,term不一直,那么有冲突
可以以已经commit的为基准,一直往前倒,倒到这个冲突的term没了,因为这个term有一个冲突,所有的应该都是不对的。返回这个冲突的index

如果自身的大,且term没问题,那么把传来的log依次加入到自己身上。

计算一个commitIndex,在穿过来的参数中,leader已经commit的,leader传过来的最后index的中选择一个最小值(选最大的没用,commit大的话,这边还不具备这么多index,commit小的话,更不能commit多了)

再在上述结果中,找到一个和自身commitindex相比的最大值。(为什么不选小的?选小的那就达不到提交新的index效果了)


chenat9
7 声望0 粉丝

引用和评论

0 条评论