MIT 6.824 Lab2C Raft之持久化
书接上文Raft Part B | MIT 6.824 Lab2B Log Replication。
实验准备
- 实验代码:
git://g.csail.mit.edu/6.824-golabs-2021/src/raft - 如何测试:
go test -run 2C -race - 相关论文:Raft Extended
- 实验指导:6.824 Lab 2: Raft (mit.edu)
实验目标
- 完成
persist()和readPersist()函数,编码方式参照注释。 - 优化
nextIndex[]回退方式,否则无法通过所有测试。
一些提示
- 测试涉及服务器故障和RPC失败等不确定事件,多次运行测试确保通过。
- 需要持久化的部分包括
currentTerm、votedFor、log。 - 有关
nextIndex[]回退优化可以查看Students' Guide to Raft。 - 在Lab2A和Lab2B中测试未能发现的错误可能会在Lab2C中暴露出来。
持久化
这部分其实很简单,代码中的注释已经很清晰了,当然你要注意data race问题。
func (rf *Raft) persist() {
w := new(bytes.Buffer)
e := labgob.NewEncoder(w)
e.Encode(rf.currentTerm)
e.Encode(rf.votedFor)
e.Encode(rf.log)
rf.persister.SaveRaftState(w.Bytes())
}
func (rf *Raft) readPersist(data []byte) {
if data == nil || len(data) < 1 {
return
}
r := bytes.NewBuffer(data)
d := labgob.NewDecoder(r)
d.Decode(&rf.currentTerm)
d.Decode(&rf.votedFor)
d.Decode(&rf.log)
}
nextIndex优化
Part B中对于失败的AppendEntries请求,让nextIndex自减,这样效率是比较慢的。
优化点1
如果follower.log不存在prevLog,让Leader下一次从follower.log的末尾开始同步日志。
优化点2
如果是因为prevLog.Term不匹配,记follower.prevLog.Term为conflictTerm。
- 如果
leader.log找不到Term为conflictTerm的日志,则下一次从follower.log中conflictTerm的第一个log的位置开始同步日志。 - 如果
leader.log找到了Term为conflictTerm的日志,则下一次从leader.log中conflictTerm的最后一个log的下一个位置开始同步日志。
nextIndex的正确位置可能依旧需要多次RPC才能找到,改进的流程只是加快了找到正确nextIndex的速度。
AppendEntries中有逻辑如下。
reply.Term = rf.currentTerm
reply.Success = false
if len(rf.log) <= args.PrevLogIndex {
reply.ConflictIndex = len(rf.log)
reply.ConflictTerm = -1
return
}
if rf.log[args.PrevLogIndex].Term != args.PrevLogTerm {
reply.ConflictTerm = rf.log[args.PrevLogIndex].Term
for i := 1; i <= args.PrevLogIndex; i++ {
if rf.log[i].Term == reply.ConflictTerm {
reply.ConflictIndex = i
return
}
}
}
Heartbeat中有逻辑如下。
if !reply.Success {
if reply.ConflictTerm == -1 {
rf.nextIndex[id] = reply.ConflictIndex
} else {
conflictIndex := -1
for i := args.PrevLogIndex; i > 0; i-- {
if rf.log[i].Term == reply.ConflictTerm {
conflictIndex = i
break
}
}
if conflictIndex != -1 {
rf.nextIndex[id] = conflictIndex + 1
} else {
rf.nextIndex[id] = reply.ConflictIndex
}
}
}
实验总结
Part C并不算是Raft算法的核心部分,关于nextIndex的优化本文是参照了Students' Guide中的方式。
如果你完成了持久化和回退优化两个部分依然无法通过所有测试,那可能要仔细的检查Part A和Part B是否遗漏了某些细节。
最后,为了证明我不是在乱写,附上我的测试结果。
MIT 6.824 Lab2C Raft之持久化的更多相关文章
- MIT 6.824 Lab2D Raft之日志压缩
书接上文Raft Part C | MIT 6.824 Lab2C Persistence. 实验准备 实验代码:git://g.csail.mit.edu/6.824-golabs-2021/src ...
- MIT 6.824 Llab2B Raft之日志复制
书接上文Raft Part A | MIT 6.824 Lab2A Leader Election. 实验准备 实验代码:git://g.csail.mit.edu/6.824-golabs-2021 ...
- MIT 6.824 Lab2A Raft之领导者选举
实验准备 实验代码:git://g.csail.mit.edu/6.824-golabs-2021/src/raft 如何测试:go test -run 2A -race 相关论文:Raft Exte ...
- MIT 6.824 lab1:mapreduce
这是 MIT 6.824 课程 lab1 的学习总结,记录我在学习过程中的收获和踩的坑. 我的实验环境是 windows 10,所以对lab的code 做了一些环境上的修改,如果你仅仅对code 感兴 ...
- MIT 6.824(Spring 2020) Lab1: MapReduce 文档翻译
首发于公众号:努力学习的阿新 前言 大家好,这里是阿新. MIT 6.824 是麻省理工大学开设的一门关于分布式系统的明星课程,共包含四个配套实验,实验的含金量很高,十分适合作为校招生的项目经历,在文 ...
- MIT 6.824学习笔记4 Lab1
现在我们准备做第一个作业Lab1啦 wjk大神也在做6.824,可以参考大神的笔记https://github.com/zzzyyyxxxmmm/MIT6824_Distribute_System P ...
- MIT 6.824 : Spring 2015 lab3 训练笔记
摘要: 源代码参见我的github:https://github.com/YaoZengzeng/MIT-6.824 Lab3: Paxos-based Key/Value Service Intro ...
- MIT 6.824 : Spring 2015 lab2 训练笔记
源代码参见我的github:https://github.com/YaoZengzeng/MIT-6.824 Lab 2:Primary/Backup Key/Value Service Overvi ...
- MIT 6.824 : Spring 2015 lab1 训练笔记
源代码参见我的github: https://github.com/YaoZengzeng/MIT-6.824 Part I: Word count MapReduce操作实际上就是将一个输入文件拆分 ...
随机推荐
- 眼见不一定为实:调用链HBase倾斜修复
hello,大家好,我是小楼. 今天给大家分享一个关于HBase数据倾斜的排查案例,不懂调用链?不懂HBase?没关系,看完包懂~ 背景 最近HBase负责人反馈HBase存储的调用链数据偶尔出现极其 ...
- dfs深搜
一.01背包dfs //回溯法,01背包 #include<iostream> #include<algorithm> using namespace std; const i ...
- apparmor 源码分析
这里不对apparmor做介绍,记录一下源码分析过程. 初始化 static int __init apparmor_init(void) -> security_add_hooks(appar ...
- Linux系统句柄优化
Linux系统句柄介绍 文件句柄,会随着进程数增加而增加.其实Linux是有文件句柄限制的,而且Linux默认一般都是1024.在生产环境中很容易到达这个值,因此这里就会成为系统的瓶颈. 在Linux ...
- C# Thread.Sleep 不精准的问题以及解决方案
1.问题 最近在写一个熔断的 SDK,其中一种策略是根据慢请求来进行熔断. 我们在测试的时候,在对应 API 里面采用了 Thread.Sleep(ms) 来模拟慢请求. 设置的慢请求阈值是 RT 1 ...
- 五、redis哨兵两套环境同一局域网容灾切换问题
上周遇到个灵异事件,实验室有两套环境来搭建redis集群和哨兵,分别是: 第一套环境IP:67(master) 65(salve) 66(salve)第二套环境IP:115(master) 116(s ...
- Linux常用命令(超详细)
一.基本命令 1.1 关机和重启 关机 shutdown -h now 立刻关机 shutdown -h 5 5分钟后关机 poweroff 立刻关机 重启 shutdown -r now 立刻重启 ...
- Jdbc从入门到入土
二刷jdbc 作者小结:从第一次大概几天快速刷完jdbc,到如今的二刷,才发现自己对jdbc的理解有点太浅.到学习javaweb是创建数据库层时的迷茫,到现在对这种设计模式的理解.我深有体会到了:实打 ...
- MySQL分库分表-理论
分库分表的几种方式 把一个实例中的多个数据库拆分到不同的实例 把一个库中的表分离到不同的数据库中 数据库分片前的准备 在数据库并发和负载没有达到限制时,不推荐水平拆分 对一个库中的相关表进行水平拆分到 ...
- 好客租房21-react组件的两种创建方式(函数组件)
1使用函数创建组件 函数组件:使用js的函数或者箭头函数创建的组件 约定1:函数组件名称必须以 开头 约定2:函数组件必须有返回值 表示该组件的结构 如果返回值为null 表示不渲染任何内容 2.1使 ...