Open ninehills opened 6 years ago
因为这个课程不希望大家Public代码,所以没有公开代码,有需要的可以单独发邮件索取。
选举状态机的实现里, 在sleep心跳时长的时候, 没有办法接受处理AppendEntriesRPC
选举状态机的实现里, 在sleep心跳时长的时候, 没有办法接受处理AppendEntriesRPC
broadcastAppendEntries()里会用协程的方式启动多个 sendAppendEntries,Reply由此处理。
Raft struct 的成员
1 Raft 节点的角色,可以使用Go常量
2 使用Buffered Channel进行异步通信,比如等待心跳包结果等情况,我定义了如下Channel
在
Make()
中需要初始化Channel为Buffered Channel3 Raft struct大部分成员都是论文的Figure 2的内容
4 发送broadcastRequestVote后,需要进行voteCount 计数,以确定是否赢得Vote,所以 Raft struct需要增加voteCount成员
协程冲突问题
Raft有如下成员来进行加锁
使用方法一般有两种,一种是在明确的边界区进行
还有一种是在函数头
加锁时要小心加锁,以确保不会发生死锁,能不加锁就不加锁。此外测试时使用
go test -race
来判断是否发生冲突善用 go 协程机制
一般用在异步触发,比如广播requestVote、AppendEntries或者异步Commit上
完整实现论文中的协议,而不要靠猜测
论文中所有的协议都需要准确实现,否则很容易出错(在互联网上找到的实现中,大部分都通不过测试),几个容易出错的地方如下,都debug了很久
Debug的方法
可以给Raft struce定义一个log方法,打印一些基本信息,如Term等,这样就不用每次都拼接。例如
当然这里图省事用的string,可以换成format,参见utils.go下的DPrintf的实现
测试
测试随机性比较大,一次测试通过不能代表没问题,建议跑多轮测试都没有问题才算通过
选举超时和心跳间隔的设定
选举状态机的实现
追求代码的美
在完成的过程中以及完成后,因为没有人帮忙判卷,看了一些现在互联网已经有的实现作为参考,总的来说,都只是为了完成而完成,注释也好、代码组织形式也好都不是很重视。可能过上几个月就忘记了以前为什么这么写的原因,这点对于Raft协议这种实现的稍微有点差池就出大问题的,非常重要。