MIT 6.5840(原6.824)个人实现记录

终于来到了最难的lab3,我做的是2024 版,新增了一个KVServer为lab2,原来的raft就变成lab3了
首先阅读论文:
Raft是一种基于日志复制的一致性算法,比paxos更加简单易学且易于实现
Raft技术特点:

  • 将问题分解为独立的易于理解和解决的子问题
  • 通过减少需要考虑的状态来简化状态空间。这使得系统更加一致并尽可能消除不确定的状态

具体的论文细节就不赘述了,网上有很多写的很好的总结,本文主要记录我的个人实现过程和细节

lab3A是实现leader的选举

  1. 首先想着把论文中Figure2中的state写进去,这一步简单地按照论文中的Figure2中写就行了
  2. 用自带的debug函数Dprintf函数探了探路,启动go test -run 3A后发现创建了3个raft。这下目标明确了:**为Raft添加状态,leader、follower、candidate。**make函数创建raft时当然是follower状态啦
  3. 这个时候就没什么思路了,到处看了看发现getstate这个函数比较好写,就写了
  4. 论文中提到了选取Leader时出现多个Leader的情况,设置一个随机的选取时间避免选取出多个Leader的情况 random
  5. 重新看了看论文的实现思路并参考了大量文章,决定使用Timer定时器和ticker循环定时器分别作为选举和心跳的定时器
  6. 实现ticker(),框架中给了for rf.killed() == false{},使用select case 调用心跳或者选举
  7. 重点实现函数electLeader,electTime到期时调用,Leader变成candidate,currentTerm++,给自己投票(voteFor=me)然后遍历rf.peers请求所有peer(类型为Candidate)为其投票,其中记录投票的票数。如果过半则当选Leader,当选后立刻给其他peer广播心跳heartBeat()
    注意:若其他peer的Term大于currentTerm则本rf退化为Follwer,currentTerm也更新为该Term
  8. 再实现心跳函数heartBeat,心跳函数用time.ticker调用,循环定时器完美满足此应用场景,只需要在心跳函数中增加一个是否为Leader的判断就行

细节

多多注意锁的使用,本人就是在锁的使用上犯了糊涂,妄图使用一把大锁来包平安,但是在并发的条件下似乎不太行得通,必须减少锁的粒度(也就是被锁住的操作)
另外还要注意锁的lock与unlock的搭配,上锁后必须解锁!!

debug

  • 多利用raft/util.go中的DPrintf函数进行分析
  • 在实现的过程中出现了warning: term changed even though there were no failures的问题,经过大量查阅资料和DPrintf来检查,先后发现了三个错误,一是重置rf的electTime的时机,二是原来心跳的定时器使用的是Timer单次定时器而不是Ticker循环定时器,三是在调用heartBeat时对它加上了锁,在heartBeat内部也加了锁,导致卡在heartBeat函数内部
  1. 有四个重置electTime的时机
    1. 给别的peer投票
    2. 收到了符合要求的heartbeat
    3. 自己发起了选举
    4. 自己是Leader,给别的Follower发送heartBeat。遍历到自己时,不需要给自己发送heartbeat,但要记得重置electTime
  2. 改用循环定时器Ticker来触发正常的心跳以便维持一个未出错的Leader任期(Term)
  3. 调用heartBeat时不需要加锁
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值