1、序言

第一次在知乎上听到了MIT 6.824这门神仙课程,正好研0阶段,研究方向也是分布式方向,趁着7月份,开始入手这门课程,大概花了一个月时间完成lab2。这里需要稍微介绍下,我觉得最好的学习方式是,先把课程仔细听完1-2遍,然后再去读paper,最后做lab。以下是个人一些心得,欢迎批评改正。

2、实验结果

100%自写代码,结果大概准确率99.5%(大概每个总共测试了500次),效果还是不错的:

3、实验介绍

主要实现选举功能、日志复制功能、持续性功能、快照功能。

这里提几点注意的:

(1)选举投票之前,只有通过预选举的server才有选举资格,才能当前轮次+1

(2)关于rpc调用,设置了50ms等待超时,超过该时间未响应,视为失败

(3)关于发送log,个人觉得此处应当加锁,而且根据log index按序发送才行(index = 3 不能比index = 2 的log先达到)

(4)关于调用rpc,处理响应时,若有bug,可能是调用rpc前的参数和rpc响应后的参数已经发生变化

(5)个人喜欢在发送心跳时,附带发送请求ack确认,即确认当前最后一个log是否已收到,便于更新commit

(6)投票请求RPC、log append RPC 我都用了条件变量+锁的方式 去判断是否已全部发送完毕;当log append RPC 并发发送时,其中一个term失败,就应该立即停止全部线程。

(7)ack心跳过期消息、append log过期消息的处理,有时候由于消息延迟,导致后发送的rpc leaderCommit更小

(8)清楚流程,别发生死锁

(9)利用dstest.py测试和dslog.py查看日志

(10)还有很多坑,主要是发生在,发送端rpc响应处理 和接收端rpc处理中,自己慢慢去踩,很宝贵的财富。

4、优点介绍

虽然代码风格做不到那么高大上,但个人代码结构还是很ok的。

raft.go 循环定时处理,发送心跳以及判断选举条件 2A.go 预选举、选举模块 2B.go 日志复制模块(发送附带ack请求确认的心跳也用该接口)、命令处理start模块 2C.go 可持续化,功能 :日志存盘,读取日志 2D.go 快照模块,功能:保存快照,读取快照 rpc.go 接受者rpc处理模块,投票请求RPC、日志复制/ack RPC、安装快照RPC

5、陷阱介绍

本人已将发现的错误日志都修复了,但是有些错误比较独特,故分享出来:

(1)关于并发响应处理

场景:(因为ack消息是心跳机制,故我的策略是可能与append并行发送)

leader :先发送心跳ack消息,后发送append

fellower:先处理ack消息(返回失败),后处理append消息(返回成功);在这里其实还可能先收到append消息,再收到ack消息

leader:先收到append响应,后收到ack响应

导致leader在处理数据时,被覆盖了

(2)fellower响应rpc请求,前0.01ms 断开连接(也可以理解为return前一瞬间断开),导致leader收到rpc响应失败,但fellower已完成rpc请求处理,考虑下这个时候会有什么影响?

(3)关于commit log 目前已解决,自己理解错了

leader只能提交当前currentTerm的log 前面任期提交的日志,在后面任期的leader也一定有 我犯的错误:未考虑提交log的term问题,而且N是递增去判断的,此处应该递减,当时以为问题不大,还方便applyCh嘛,结果就出现了fig8一模一样的情况。一定要去理解fig8在说什么。

精彩链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: