mit6.824 lab2a-raft选举

初步实现raft选举,保证一个任期仅有一个leader,在leader宕机后其他follower会自动拉票竞选成为leader。

大致思路

  1. 最初所有服务器都为follower,并且初始化一个选举计时器(300~400ms)。当选举计时器超时,follower会成为candidate进行竞选投票,如果candidate得到大部分的选票,则会成为leader
  2. leader会定期发送心跳包以及重置自己的选举计时器,防止新的一轮选举在自己未宕机的情况下开始。

RPC部分

//请求投票:候选者想要成为leader
func (rf *Raft) RequestVote(args *RequestVoteArgs, reply *RequestVoteReply)
//复制log 或 心跳包(log为空时为心跳包)
func (rf *Raft) AppendEntries(args *AppendEntriesArgs, reply *AppendEntriesReply)

注意:rpc会被多个服务器调用,需要全程加锁

服务器接收到任何任期高于自己的rpc后,会更新自己的任期。

RequestVote:

1.向当前服务器请求投票,如果candidate的任期<当前服务器的任期,则会拒绝投票。
2.在收到投票请求后,自身转变为follower,并且重置自己的选举超时时间。
3.如果candidate的任期合法并且leader在最新任期没有进行投票,则投票给candidate。

AppendEntries:

1.若leader任期<当前服务器任期,则直接返回
2.服务器在接收到心跳包时,会转变成follower,并且重置自己的选举计时器。

实现细节

  • 成为候选人:1.增加term 2.选举自己 3.重置选举计时器 4.并行发送投票请求
  • 并行向其他服务器请求投票:
for i := 0; i < len(rf.peers); i++ {
				reply := RequestVoteReply{0, false}
				if i != rf.me {
					go func(i int, args RequestVoteArgs, reply RequestVoteReply, rf *Raft) {
						if rf.status == "candidate" {
							rf.sendRequestVote(i, &args, &reply) //发送请求投票rpc
						}
						if reply.VoteGranted == true {
							//获得投票
							rf.SuccessVoteNum++
						} else {
							//未获取投票
						}
						ch <- reply 
						finishVoteNum++
					}(i, args, reply, rf)
				}
			}
			//完成全部投票或者得到的投票数过半时停止等待
			for {
				select {
				case <-ch:
					if finishVoteNum == len(rf.peers)-1 || rf.SuccessVoteNum > len(rf.peers)/2 {
						goto checkTerm //这里只有goto+标签和break+标签能够退出
					}
				}
			}

		checkTerm:
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值