[经验分享]MIT6.824 Lab2ABCD 实现一个raft库

这个实验我做了将近20个工作日,耗时真挺久

温馨提示

1.写一个getlast函数,专门用来查最后一条log,一个get函数,输入index,返回log

2.做好备份,你的很多修改带来的变化是很大的.这里我用的vscode远程开发,有个时间线的功能,我觉得非常好用,墙裂推荐.

3.Debug

const Debug = false

func DPrintf(format string, a ...interface{
   }) (n int, err error) {
   
	if Debug {
   
		file := "./" + "log_kv" + ".txt"
		logFile, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0766)
		if err != nil {
   
			panic(err)
		}
		log.SetOutput(logFile) // 将文件设置为log输出的文件
		log.Printf(format, a...)
	}
	return
}

Lab2A:leader选举

1.通读raft论文 重点阅读firgure2

2.Start early,千万不要一直沉浸在论文,快点开始,很多东西都会豁然开朗,如果你不动,光用脑子想,会很累

由于步骤太多,我只讲一些重要函数中(很抱歉,我不能提供的代码,过段时间我在开放)

1. func (rf *Raft) RequestVote(args *RequestVoteArgs, reply *RequestVoteReply)

  • 判断args.Term,如果更小则拒绝
  • 更新CurrentTerm,如果args.Term更大就更新(这里注意一定要把peer调成candidate,为什么我后面会讲)
  • restrict election 得到最后一个日志的Term 和 Index
    • 如果args.LastLogTerm更小 说明不够新 拒绝
    • 如果Term一样 Index更小 说明不够新 拒绝
  • 判断是否重复投票 如果已经投票,并且投给的不是args.CanidateId && args.Term==CurrentTerm,拒绝
  • 上面的情况都没有出现,可以投票

2.func (rf *Raft) ticker()

每当启动一个peer,都要 go ticker(),我的ticker与election都写的很乱,很多地方没有梳理

for !rf.killed()	{
	if peer是follower && 超时未收到心跳 {
    	转为 candidate
    	随机休眠一段时间
    	如果休眠结束 状态不是 candidata {
    		go ticker()
    		return
    	}
    	开始选举
    	return
    }
    if peer是leader && Term时间耗尽{
    	转为 candidate
    	随机休眠一段时间
    	如果休眠结束 状态不是 candidata {
    		go ticker()
    		return
    	}
    	开始选举
    	return 
    }
	if peer是leader {
		发送心跳
	}
	休眠一段时间
}

Lab2B

1.raft论文细看

2.多打印日志,我基本上在每个函数的第一行都会打印输入的参数

func (rf *Raft) AppendEntries(args *AppendEntriesArgs, reply *AppendEntriesReply)

这个函数是我写的最长的函数了,在我第一次完成lab2B,之后任然在修改,缝缝补补.

由于没有重构,还留存一些没用的部分,所以看起来会很乱

func (rf *Raft) AppendEntries(args *AppendEntriesArgs, reply *AppendEntriesReply) {
   
	rf.mu.Lock()
	defer rf.mu.Unlock()
	defer DPrintf("raft.me=%d args %v reply %v", rf.me, args, reply)
	DPrintf("raft.me=%d rf.LastSsIndex %d rf.CurrentTerm %d get %d  rpc AppendEntries but no judge args %v log %v",
		rf.me, rf.LastSsIndex, rf.CurrentTerm, args.Me, args, rf.Log)
	rf.now = time.Now()
	reply.Term = rf.CurrentTerm

	if args.CurrentTerm == rf.CurrentTerm && rf.Raftstate == 1 {
   
		DPrintf("raft.me=%d refuse follower's append RPC", rf.me)
		return
	}
	//if args.CurrentTerm 更小 拒绝
	if args.CurrentTerm < rf.CurrentTerm {
   
		DPrintf("raft.me=%d refuse %d append because of term args.CurrentTerm %d < rf.CurrentTerm %d",
			rf.me, args.Me, args.CurrentTerm, rf.CurrentTerm)
		reply.Append = false
		return
	}
	// if args.CurrentTerm 更大 更新Term,将状态设置成follower

	if args.CurrentTerm > rf.CurrentTerm {
   
		DPrintf("r
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值