Raft算法同步过程

40次阅读

共计 1054 个字符,预计需要花费 3 分钟才能阅读完成。

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 效果了)

正文完
 0