6.824 Lab2实现细节
以下是我在实现lab2的过程中的一些思路以及问题总结:
1. Lab2A
Lab2A需要实现领导人的选取,首先介绍思路,根据论文来进行实现,这部分还是很容易的,只不过中间出现了一点小bug。先上测试结果:
借鉴了其他大佬的实现之后,整体思路:实现raft的基本数据结构(这部分完全按照论文的图2进行设置),然后实现
resetTimer
函数,这个函数的作用就是实现了一个定时器,根据定时器的时间触发TimeoutElection()
函数,它的作用就是用来处理当我们的节点初始化之后,根据不同的随机时间进入竞选领导人的环节。竞选领导人时,首先要更新自己的状态,然后进行发送投票请求,投票请求函数由
sendRequestVote
实现,实现一个rpc请求,远程调用RequestVote
函数(这里应该是广播?),该函数用来实现raft接收到投票请求后执行的动作,比较候选人的日志信息,term信息,以及是否已经投过票了,都ok后投票给该候选人,并且将自己设置为FOLLOWER。现在FOLLOER已经将票投出去了,候选人则需要一个处理这些投票结果的函数
HandleRequestVote
,处理接收的reply,比较投票的结果,当前term与返回的term进行比较,如果返回的更新,则将自己更新为FOLLOWER,否则,计算票数,如果当选,改变自己的状态,初始化相关参数。开始发送心跳包…
RequestVote
错误版本如下(等我有空再来说说哪里出错了):
首先判断是否投过票
if rf.votedFor == -1 {
//判断任期,若任期小于请求者,则将自己设置为FOLLOWER
if args.Term > rf.currentTerm {
rf.current_state = "FOLLOWER"
rf.currentTerm = args.Term
rf.votedFor = -1
rf.vote_counts = -1
//接着比较日志
if len(rf.logs) > 0 {
loglength := len(rf.logs)
if rf.logs[loglength-1].Term < args.LastLogTerm && loglength-1 < args.LastLogIndex {
//比较完成之后进行投票,并记录下投票的id
rf.votedFor = args.CandidateId
reply.Term = args.Term
reply.VoteGranted = true
return
}
}
}
}
reterm := -1
if rf.currentTerm > args.Term {
reterm = rf.currentTerm
} else {
reterm = args.Term
}
reply.Term = reterm
reply.VoteGranted = (rf.votedFor == args.CandidateId)
return
//判断日志条目
通过测试版本:
voting := true
// 此节点日志比请求者的日志新
if len(rf.logs) > 0 {
if rf.logs[len(rf.logs)-1].Term > args.LastLogTerm ||
(rf.logs[len(rf.logs)-1].Term == args.LastLogTerm &&
len(rf.logs)-1 > args.LastLogIndex) {
voting = false
}
}
// 此节点Trem大于请求者 忽略请求
if args.Term < rf.currentTerm {
reply.Term = rf.currentTerm
reply.VoteGranted = false
return
}
// 此节点Trem小于请求者
if args.Term > rf.currentTerm {
rf.current_state = "FOLLOWER"
rf.currentTerm = args.Term
rf.votedFor = -1
if voting {
rf.votedFor = args.CandidateId
}
rf.resetTimer() //重置超时事件
reply.Term = args.Term
reply.VoteGranted = (rf.votedFor == args.CandidateId)
return
}
// Term相同 判断是否需要投票
if args.Term == rf.currentTerm {
if rf.votedFor == -1 && voting { // 未投过票且日志没有问题 可以投票
rf.votedFor = args.CandidateId
}
reply.Term = rf.currentTerm
reply.VoteGranted = (rf.votedFor == args.CandidateId)
return
}
2 .Lab2B
未完待续…