我也终于刷完 MIT 6.824 2020 了

2020-03-06 19:36:19 +08:00
 yzongyue

今年只是 lab1 改版,后面的实验和前面几年没有区别;目前的代码有个 test 偶现了一次 FAIL, 又跑了几百次没跑出来。。。 源码在 github

5786 次点击
所在节点    程序员
20 条回复
ysn2233
2020-03-06 19:41:24 +08:00
记得当年 2 还是 3 有个 unrealible figure 8 一直不能 100%过,调试的气死后来就弃了
arjen
2020-03-06 19:42:11 +08:00
唉,我连 lab1 都没有动力刷下去(话说这个好像不让放 github 上
yzongyue
2020-03-06 19:44:12 +08:00
@ysn2233 我是隔几天刷一下,不然太打击信心了
yzongyue
2020-03-06 19:47:04 +08:00
@arjen 再来刷下吧。。。我看到 github 上有不少人都放了,估计 MIT 的学生也不需要看我这种答案
Weny
2020-03-06 21:01:05 +08:00
@arjen 过 deadline 放 github 应该问题不大吧
aaahhh123
2020-03-06 21:13:11 +08:00
666
polebug
2020-03-06 22:51:16 +08:00
同在写 6824 qaq 还没写完
PythonYXY
2020-03-09 01:20:56 +08:00
之前只刷完了 lab1,2,lz 觉得 lab3,4 相比 lab2 分量怎样?
yzongyue
2020-03-09 07:29:45 +08:00
@PythonYXY 最复杂的是 lab2,lab34 相对简单些,lab3 需要给 raft 加快照,好多 lab2 的 bug 会冒出来,我觉得至少做完 lab3 才算完整吧
hallDrawnel
2020-03-10 16:22:00 +08:00
课程的论文都看完了?
yzongyue
2020-03-10 16:37:07 +08:00
@hallDrawnel 只写了 lab,所以只看了 raft
endlessroad1991
2020-05-19 03:05:54 +08:00
回复题主,帮你抓了个 bug 。

https://github.com/yzongyue/6.824-golabs-2020/blob/yzy/src/raft/raft_vote.go#L125 这里在 rf.changeRole()之前,应该确保 rf.role == Follower && rf.voteFor == -1 。

否则,该节点在 rf.changeRole()之前可能已经 approve 了其他节点在当前 term 的 vote request (并修改了 rf.voteFor ),然后在这里 rf.changeRole()的时候又投票给自己( rf.voteFor = rf.me )。这样该节点就会投出两个不同的票,从而可能造成当前 term 有两个不同节点成为 leader 的情况。

详细例子:假设 3 个节点 A,B,C 。
1. A 成为 candidate, 发送 vote request 给 B 。
2. B 收到 A 的 vote request 时仍然是 follower,因此批准 vote request 。
3. A 收到 B 的 approval,认为自己成为 leader 。
4. B 成为 candidate,并收到 C 的 approval,认为自己成为 leader 。

这里有一个问题是,为什么 2 之后,4 仍然可能发生?在 B 批准 A 的 vote request 时,B 重置了自己的 electionTimer: https://github.com/yzongyue/6.824-golabs-2020/blob/yzy/src/raft/raft_vote.go#L67 。所以 B 不应该再触发将自己变为 candidate 的逻辑 https://github.com/yzongyue/6.824-golabs-2020/blob/yzy/src/raft/raft.go#L415

我的理解是,2 和 4 之中,事实上先发生的是 4 ( B 触发自己变为 candidate 的逻辑 https://github.com/yzongyue/6.824-golabs-2020/blob/yzy/src/raft/raft.go#L415 )。但很不幸,在调用 rf.startElection()时,go runtime scheduler 将本 goroutine 暂停,而切换到执行 2 的 goroutine (处理 A 的 vote request )!如果把 rf.startElection() inline,就不会出现这个 bug 。这也能解释为什么这个 bug 很难复现:这依赖于 go runtime scheduler 对这些 concurrent events 的执行时机。
endlessroad1991
2020-05-19 03:08:37 +08:00
"如果把 rf.startElection() inline,就不会出现这个 bug 。“

请忽略这句话。。就算把 rf.startElection() inline,在那个 function 里面,仍然还有别的 function call 。所以仍然可能被 go runtime scheduler 切换出去。所以 bug 仍然可能存在
yzongyue
2020-05-19 09:40:07 +08:00
@endlessroad1991 多谢大神,确实需要先判断下,有时间我改改
yzongyue
2020-05-19 09:41:45 +08:00
@endlessroad1991 ps:大神们这么努力的嘛,6 小时前是凌晨三点?
yzs981130
2020-05-25 00:31:38 +08:00
lz 好,raft 里面 vote 部分,https://github.com/yzongyue/6.824-golabs-2020/blob/yzy/src/raft/raft_vote.go#L58 这里判断否 up-to-date,为何放在更改了自身 role ( https://github.com/yzongyue/6.824-golabs-2020/blob/yzy/src/raft/raft_vote.go#L55 )的后面判断呢?我的理解是当网络 split,小部分独立节点一直 vote 会把 term 拉高,网络恢复时大部分节点虽然 term 比较低,但是 log 更新,所以不受影响,此时不应该把自己变成 follower ?
yzs981130
2020-05-25 00:59:24 +08:00
@yzs981130 啊我理解错了不好意思 在助教的 guide 里面有说 您是对的
yzongyue
2020-06-07 21:58:45 +08:00
@endlessroad1991 啊,,,不对,我发现之前的代码没问题,因为每次 change role 为 candidate 时,term += 1,
所以你给的情景不会出现同一 term 投出两票的情况
endlessroad1991
2020-06-08 00:53:25 +08:00
@yzongyue 啊哈,你是对的。

你当时 fail 的哪个 test ?是正确性问题(两个 server 同样 index,apply 了不同的 log )还是某个 test 没能在规定时间内完成选主?
yzongyue
2020-06-08 07:43:02 +08:00
@endlessroad1991 忘了。。。当时没开 log 不确定到底是什么问题,能确定的是代码还有 bug

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/650515

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX