【分布式】MIT 6.824 Lab 2B实现细节分析
基于6.824 2020版 http://nil.csail.mit.edu/6.824/2020/schedule.html
Lab 2A(选举)一天就完成了,主要是第一次开始写Raft需要稍微熟悉一下,但是几乎不用修改,很容易就通过了。不过到了Lab 2B就会发现2A能够通过纯属侥幸,有很多小细节逻辑错误,是由于2A的限制不大还是能够通过。
Lab 2B的完整实现花了整3天,调试就花了一天半,首先修改2A的遗留问题就要花其中接近一个白天。而且这还是我先看了LEC 5、6、7,以及Assign中的到Lab 2B(也就是log 复制与提交)相关建议/提示之后再完成的,这些准备的内容就花了快一个礼拜(因为不是光看就得了,觉得重点的要标记,由于是英文,一边看能看懂但为了再翻的时候方便还是要适当翻译一下)。
整个实现完全没有看课程网站以外的资料,尤其是其他人的实现。当然确实也不能保证2A完全正确,但是我连续运行过了测试脚本5次以上,可能一定程度上是正确的(例如,最后一次的bug会在运行大致3次时在倒数第二个项目,也就是在TestBackup2B爆出来)(同时由于我shell脚本还不太熟练,LEC 5提供的go-test-many.sh直接用有点问题,暂时还没有用)。
wangjy@DESKTOP-861RECN:~/research/6.824/src/raft$ time go test -run 2B
Test (2B): basic agreement ...... Passed -- 0.7 3 16 4804 3
Test (2B): RPC byte count ...... Passed -- 1.4 3 48 115376 11
Test (2B): agreement despite follower disconnection ...... Passed -- 4.3 3 124 33193 7
Test (2B): no agreement if too many followers disconnect ...... Passed -- 3.5 5 324 72078 3
Test (2B): concurrent Start()s ...... Passed -- 0.7 3 12 3624 6
Test (2B): rejoin of partitioned leader ...... Passed -- 6.1 3 305 75278 4
Test (2B): leader backs up quickly over incorrect follower logs ...... Passed -- 15.5 5 2800 2269915 102
Test (2B): RPC counts aren't too high ...... Passed -- 2.1 3 38 12074 12
PASS
ok _/home/wangjy/research/6.824/src/raft 34.290sreal 0m34.960s
user 0m2.211s
sys 0m2.627s
我还在课程提供的日志函数的基础上又封装了一个小Log打印工具,会在打印内容前加上当前的节点编号(即rf.me),个人感觉会看着方便一点。
func (rf *Raft) PeersDPrintf(format string, a ...interface{}) {content := fmt.Sprintf(format, a...)number := strconv.Itoa(rf.me)blankLeft := ""blankRight := ""for i:=0;i<rf.me;i++ {blankLeft = blankLeft + " "}for i:=rf.me+1;i<len(rf.peers);i++ {blankRight = blankRight + " "}blankRight = blankRight + " "DPrintf("Peers " + blankLeft + number + blankRight + content)
}
显示效果:
wangjy@DESKTOP-861RECN:~/research/6.824/src/raft$ time go test -run 2B
Test (2B): basic agreement ...
2023/11/15 21:38:07 Peers 0 change from [Follower]-Term[0]-Vote[0] to [Candidate]-Term[1]-Vote[0] with last log[0]-Term[0]
2023/11/15 21:38:07 Peers 0 change from [Candidate]-Term[1]-Vote[0] to [Leader]-Term[1]-Vote[0] with last log[0]-Term[0]
2023/11/15 21:38:07 Peers 0 ~~~~~~~~~~~~~~ become Leader of Term[1] ~~~~~~~~~~~~~~
2023/11/15 21:38:07 Peers 0 receive log[1] at Term [1]
2023/11/15 21:38:07 Peers 1 log len[0] match [0] append to len[1]
2023/11/15 21:38:07 Peers 2 log len[0] match [0] append to len[1]
2023/11/15 21:38:07 Peers 0 receive LogAppend reply from ind[1], termStamp[1], currentTerm[1], prevLogIndex[0]-Entries len[1]; Success[true]
2023/11/15 21:38:07 Peers 0 update commit from [0] to [1]
2023/11/15 21:38:07 Peers 0 response for log[1]
2023/11/15 21:38:07 Peers 0 receive LogAppend reply from ind[2], termStamp[1], currentTerm[1], prevLogIndex[0]-Entries len[1]; Success[true]
2023/11/15 21:38:07 Peers 1 increase commitIndex from [0] to [1]
2023/11/15 21:38:07 Peers 2 increase commitIndex from [0] to [1]
这里提供一些个人在debug时遇到的原文中没有的个人实现的细节,或注意事项。当然课程已经提到了最重要的点是要按照原文的图2来实现,在此基础上,我自己总结的问题/关键点是:
- 每次收到RPC返回的信息时,重新获取锁后都要校验保证当前的一些状态没变,例如几乎每次都要校验的:currentTerm号或membership(Leader、Candidate或Follower),这种问题其实LEC 5也强调了。
- 注意Lab 2B校验程序是会收集每个节点向各自applyCh提交的ApplyMsg然后进行校验,所以每个从节点也要发送applyCh。
- 注意每次当选Leader后要重置nextIndex[]和matchIndex[]
- 注意对于一些开启新协程的任务,如选举倒计时——需要标记一个时间戳,然后在time.Sleep后校验,或是发送选票——需要标记选举term戳等,这里的如“时间戳”和“term戳”需要作为参数传入对应使用go调用的函数,同时调用的时候是判断需要进行状态转换并持有锁的(也就是类似CAS问题)。
- 收到投票的节点的角色和状态可能各种各样,但是如何处理原文并没有交代得很详细,这里有两个关键点(主要是要防止我们在后期实现时过度设计):
a. 一个Term只有一个Leader能够当选。或者换句话说,一个Term最多属于一个Leader。
b. 一个Follower在一个Term中只能给一个Candidate投票,绝不能给其他Candidate投票。 - 任何节点的currentTerm是不能回退的(这个课程中有提及为什么),所以如果Candidate和Leader收到了带有高的Term的RequestVote,即使发送者的log不够Up-to-date,其也要更新自己的Term,然后进行相应操作,例如Leader要先退位在参选等等。否则该发送者(不够Up-to-date的Candidate)会一直试图选举,这样该节点就不可用了。
- 有个问题是,当一个leader累积了很多未提交的log后,又成为了Follower。由于从节点也要更新commitIndex,并提交log到自己的applyCh,那么其commitIndex一定要在至少与新Leader对齐过一次再用AppendEntries中的LeaderCommit更新,否则会提交没有共识的log。我这里通过限制match包和心跳包的内容来实现。(这一点就是我在TestBackup2B爆出的bug)
然后这里有个自己的设计的一个小数据结构,如何更新Leader的commitIndex呢?——在更新了一个从节点的matchIndex后触发,维护第majority个大的matchIndex[]即为commitIndex(Leader自己的matchIndex等于自己的log长度)
相关文章:
【分布式】MIT 6.824 Lab 2B实现细节分析
基于6.824 2020版 http://nil.csail.mit.edu/6.824/2020/schedule.html Lab 2A(选举)一天就完成了,主要是第一次开始写Raft需要稍微熟悉一下,但是几乎不用修改,很容易就通过了。不过到了Lab 2B就会发现2A能够通过纯属侥…...
MySql 数据库初始化,创建用户,创建数据库,授权
登录MySQL(使用管理员账户) mysql -u root -p 设置用户 -- 创建用户并设置密码 CREATE USER user_name% IDENTIFIED BY user_password;-- 删除用户 drop user user_name; 设置数据库 -- 创建数据库 CREATE DATABASE database_name;-- 删除数据库 DR…...
【洛谷算法题】P5712-Apples【入门2分支结构】
👨💻博客主页:花无缺 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5712-Apples【入门2分支结构】🌏题目描述🌏输入格式&…...
vue项目中的js文件使用vuex
使用场景:假设有一个接口,需要在很多页面获取一遍并且将接口的返回值保存起来,这样就能使用vuex,将值保存在vuex中 实现:vuex中新建firmModule.js文件,编写存储值的代码,utils/getFirmData.js用…...
【Vue3】 computed 完整写法 全选反选 、计算商品总价
全选反选 const allCheck computed({get() {return buyCard.value.every(item > item.checkState)},set(val) {return buyCard.value.forEach(item > item.checkState val);},}); 计算商品总价格 const aggregatePrice computed(() > {const arr buyCard.value.f…...
Mindomo Desktop for Mac(免费思维导图软件)下载
Mindomo Desktop for Mac是一款免费的思维导图软件,适用于Mac电脑用户。它可以帮助你轻松创建、编辑和共享思维导图,让你的思维更加清晰、有条理。 首先,Mindomo Desktop for Mac具有直观易用的界面。它采用了Mac独特的用户界面设计…...
Spark资源规划-资源上线评估
1、总体原则 以单台服务器 128G 内存,32 线程为例。 先设定单个 Executor 核数,根据 Yarn 配置得出每个节点最多的 Executor 数量,每个节点的 yarn 内存/每个节点数量单个节点的数量 总的 executor 数单节点数量*节点数。 2、具体提交参数 …...
RT-Thread STM32F407 定时器
定时器简介 硬件定时器一般有 2 种工作模式,定时器模式和计数器模式。不管是工作在哪一种模式,实质都是通过内部计数器模块对脉冲信号进行计数。下面是定时器的一些重要概念。 计数器模式:对外部输入引脚的外部脉冲信号计数。 定时器模式&…...
C#asp.net考试系统+sqlserver
C#asp.net简易考试系统 sqlserver在线考试系统学生登陆 判断学生是否存在 选择课程名 科目 可以进行答题操作,已经考试的课程不能再次答题, 自动根据课程名对应的题库生成试卷界面 加入选项类容 说明文档 运行前附加数据库.mdf(或sql生成数…...
mac上配置maven
本文简述mac book上的Maven环境配置,着重讲述不同点。 1.安装 下载解压后,首先配置环境变量。编辑~/.bash_profile文件。加入如下代码: export M2_HOME/Users/jackie/tools/apache-maven-3.8.1注意:“/Users/jackie/tools/apac…...
解决vue-cli node-sass安装不成功问题
在项目中安装 vue-cli node-sass不成功解决办法如下: npm install node-sass --save 若以上方式安装不成功(安装超时), 则使用以下的方法: 1. npm install -g cnpm --registryhttps://registry.npm.taobao.org 2. cnpm in…...
【Mysql】Mysql内置函数介绍
🌈欢迎来到Python专栏 🙋🏾♀️作者介绍:前PLA队员 目前是一名普通本科大三的软件工程专业学生 🌏IP坐标:湖北武汉 🍉 目前技术栈:C/C、Linux系统编程、计算机网络、数据结构、Mys…...
【Linux】vscode远程连接ubuntu失败
VSCode远程连接ubuntu服务器 这部分网上有很多,都烂大街了,自己搜吧。给个参考连接:VSCode远程连接ubuntu服务器 注意,这里我提前设置了免密登录。至于怎么设置远程免密登录,可以看其它帖子,比如这个。 …...
如何设计开发一对一交友App吸引更多活跃用户
在当今社交媒体时代,一对一交友App开发正日渐成为发展热点。如何吸引更多活跃用户成为开发者们的首要任务。通过本文,我们将探讨一系列方法,助您设计开发一对一交友App,吸引更多用户的关注和参与,提升App的活跃度。 了…...
UE基础篇六:音频
导语: 通过实现一个小游戏,来学会音频,最后效果 入门 下载启动项目并解压缩。通过导航到项目文件夹并打开SkywardMuffin.uproject来打开项目。 按播放开始游戏。游戏的目标是在不坠落的情况下触摸尽可能多的云。单击鼠标左键跳到第一朵云。 游戏很放松,不是吗?为了强调…...
vscode+python开发之虚拟环境和解释器切换
需求情景: 现在我们要开发多个项目比如:项目A,项目B、项目C,他们每个项目需要依赖不同的库。每个项目依赖的解释器也不一样怎么办? 项目A:需要在python3.7环境运行 依赖aadd3.2库 项目B、需要在python3.11…...
vite 样式按需加载
用于按需引入组件库样式的插件。 vite-plugin-impvite-plugin-style-import 以上两个插件可以实现按需引入组件库样式,尝试后发现vite-plugin-imp这个插件目前有个问题是,它支持按照组件动态引入组件内部的样式,但是antd还定义了一些全局样…...
Flutter打包iOS过程中pod访问github失败
问题描述 执行Flutter打包iOS命令出现如下错误: # flutter build ios ...Error output from CocoaPods: ↳Cloning into /var/folders/q8/sd0qtp6d69b30yt6gsh1jrg40000gq/T/d20231116-58127-8g2zje...fatal: unable to access https://github.com/ccgus/fmdb.git…...
使用VMware安装linux虚拟机
文章目录 一、介绍二、下载VMware三、下载centOS镜像文件四、新建虚拟机1. 选择配置类型2. 安装centOS操作系统3. 命名4. 指定磁盘容量5. 虚拟机配置信息确认6. 稍后选择系统镜像 五、安装虚拟机1. 选择语言2. 设置时间、系统、以及yum源3. 开始安装4. 设置root用户密码5. 完成…...
Kafka、RocketMQ、RabbitMQ的比较总结Kafka、RocketMQ、RabbitMQ的比较总结
【精选】Kafka、RocketMQ、RabbitMQ的比较总结_kafka rabbitmq rocketmq_【江湖】三津的博客-CSDN博客...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
