Raft的每个实例维护着一个nextIndex
数组,这个数组在leader状态使用。
记录每一个follower下一个应该放置的log的下标
leader发送的第一个AppendEntries
RPC往往是一个空的包(不包含日志数据的心跳包,大部分时候是空的,如果当选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效果了)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。