MIT 6.824: Distributed Systems- 实现Raft Lab2B

接上文《MIT 6.824: Distributed Systems- 实现Raft Lab2A》,本篇实现Raft Lab2B作业,即实现日志同步。

已通过MIT单元测试:

Lab2B实现

相比较Lab2A的选主来说,Lab2B则集中精力在appendEntriesRPC部分,坑明显变多,最后我会总结一下,先上代码。

Node启动阶段

Start写入操作

appendEntries RPC发起方(仅leader有效)

appendEntries RPC接收方

日志提交协程

总结Lab2B

  • nextIndex是leader对follower日志同步进度的猜测,matchIndex则是实际获知到的同步进度,leader需要不断的appendEntries来和follower进行反复校对,直到PrevLogIndex、PrevLogTerm符合Raft论文约束。
  • Leader更新commitIndex需要计算大多数节点拥有的日志范围,通过对matchIndex排序找中位数的index,就是大多数节点都拥有的日志范围,将其设置为commitIndex。
  • Follower收到appendEntries时,一定要在处理完log写入后再更新commitIndex,因为论文中要求Follower的commitIndex是min(local log index,leaderCommitIndex)。
  • Leader在不断调整某个follower的nextIndex过程中,注意不要让nextIndex减小到1以下,因为nextIndex的语义是follower的下一个日志写入下标。
  • requestVote接收端,一定要严格根据论文判定发起方的lastLogIndex和lastLogTerm是否符合条件,这里很容易写错。
  • appendEntries接收端,一定要严格遵从prevLogIndex和prevLogTerm的论文校验逻辑,首先看一下prevLogIndex处是否有本地日志(prevLogIndex==0除外,相当于从头同步日志),没有的话则还需要leader来继续回退nextIndex直到prevLogIndex位置有日志。在prevLogIndex有日志的前提下,还需要进一步判断prevLogIndex位置的Term是否一样。
  • appendEntries接收端返回success=true的前提必须是将leader传来的日志处理完了并且更新了commitIndex之后。
  • appendEntries接收端,要做好日志冲突时的后续全部截断逻辑。
  • 注意当log、voteFor、commitIndex三个状态变化后,返回RPC前一定要persist()持久化一下(Lab2B并不要求persist,但是Lab3C要求,所以在这里先做好,免得Lab2C回头加)
  • 日志提交通过一个独立的goroutine实现就行,定期判断lastApplied和commitIndex之间的有日志就提交即可,注意提交效率(copy出来释放掉锁,然后往应用层推)

如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~