【分布式】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博客...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...
第八部分:阶段项目 6:构建 React 前端应用
现在,是时候将你学到的 React 基础知识付诸实践,构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段,你可以先使用模拟数据,或者如果你的后端 API(阶段项目 5)已经搭建好,可以直接连…...
