【分布式】MIT 6.824 Lab 2C实现细节分析

写完Lab2B后搞大论文,又回来做的Lab2C

在Lab2B基础上简单实现persist后无法通过测试样例Test (2C): Figure 8。根据raft图2的最后一个提示,更新commitIndexi的时候要校验log[i-1].Term == currentTerm。这个原理(可能包括raft整个文章)要重新整理下。

但是接下来TestFigure8Unreliable2C卡了很长时间(可能断断续续有一个礼拜了),就是所谓的样例Test (2C): Figure 8 (unreliable) ...。这里把原文细节(重点是Fig8的细节和原文5.4节的逻辑)和Students’ Guide to Raft又过了一下,也改进了一些点。

  • 收到AppendEntries包后,就算对上了PrevLogIndex,也要:
    • 加标志位,判断该Term更新过至少一次的话,是不是过时的AppendEntries包,使得log变短。
    • 是否甚至是其他Term的过时包:
      • 如果PrevLogIndexargs.Entries 少等于已有log,只检查最后的 args.Entries 对应位置条目的Term,与已有log不一致则替换
      • 如果PrevLogIndexargs.Entries 多于已有log,直接替换
  • 收到的是AppendEntries包,commitIndex更新的大小不能高于本次args.PrevLogIndex + len(args.Entries)
  • 日志对齐函数中,取消过时包:
    • reply.Success == truematchIndex不能降低
    • reply.Success == false 的逻辑没注意,下面就是这个问题)
  • 选举计票优化了下,不用等所有票投完,只有赞成票和拒绝票都不够majority才继续cond.Wait(),同时要判断当前还是Candidate、Term没变

但还是不行,也就是像解决Lab2B问题时那样不依赖调试是不行了,然后搜了一下TestFigure8Unreliable2C,似乎个人的问题都不同。不过还是得到一些提示,虽然已经开始阅读甚至改造config.gotest_test.go了,但是有个githubIssue总结得确实好一点:

TestFigure8Unreliable2C 这测试用例一共运行不超过40s。前10秒在可靠网络各种插入数据。中间20秒,在不可靠网络中各种插入数据。最后10s,开始的时候,恢复网络,插入一个数据,等待这个数据被提交,如果超过这10s就报错。

这里本人补充一点:最后校验时必须所有节点(5个)全部提交(提交到applyCh)。
这里改进了无数次调试输出信息,需要注意几组关键值,还有些方便观察的技巧:

  • 注意每个节点的rf.lastApplied,rf.commitIndex,len(rf.log)
  • 注意所有时刻rf.matchIndexrf.nextIndex

最终发现我最后的问题是,在最后一个Term中,Leader已经对齐某节点的matchIndexnextIndex后收到过时包,导致nextIndex单独回退,使得后续不给该节点发AppendEntries了。(因为我的实现中新当选后从节点日志对齐和日志发送是两个函数,日志对齐函数理论上所有节点都对齐就结束了)所以问题还是没有在一处细节上处理好过时包。
注意,使用命令可单独测试某组样例:

go test -run TestFigur
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值