当前位置: 首页 > news >正文

【分布式】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来实现,在此基础上,我自己总结的问题/关键点是:

  1. 每次收到RPC返回的信息时,重新获取锁后都要校验保证当前的一些状态没变,例如几乎每次都要校验的:currentTerm号或membership(Leader、Candidate或Follower),这种问题其实LEC 5也强调了。
  2. 注意Lab 2B校验程序是会收集每个节点向各自applyCh提交的ApplyMsg然后进行校验,所以每个从节点也要发送applyCh。
  3. 注意每次当选Leader后要重置nextIndex[]和matchIndex[]
  4. 注意对于一些开启新协程的任务,如选举倒计时——需要标记一个时间戳,然后在time.Sleep后校验,或是发送选票——需要标记选举term戳等,这里的如“时间戳”和“term戳”需要作为参数传入对应使用go调用的函数,同时调用的时候是判断需要进行状态转换并持有锁的(也就是类似CAS问题)。
  5. 收到投票的节点的角色和状态可能各种各样,但是如何处理原文并没有交代得很详细,这里有两个关键点(主要是要防止我们在后期实现时过度设计):
    a. 一个Term只有一个Leader能够当选。或者换句话说,一个Term最多属于一个Leader。
    b. 一个Follower在一个Term中只能给一个Candidate投票,绝不能给其他Candidate投票。
  6. 任何节点的currentTerm是不能回退的(这个课程中有提及为什么),所以如果Candidate和Leader收到了带有高的Term的RequestVote,即使发送者的log不够Up-to-date,其也要更新自己的Term,然后进行相应操作,例如Leader要先退位在参选等等。否则该发送者(不够Up-to-date的Candidate)会一直试图选举,这样该节点就不可用了。
  7. 有个问题是,当一个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&#xff08;选举&#xff09;一天就完成了&#xff0c;主要是第一次开始写Raft需要稍微熟悉一下&#xff0c;但是几乎不用修改&#xff0c;很容易就通过了。不过到了Lab 2B就会发现2A能够通过纯属侥…...

MySql 数据库初始化,创建用户,创建数据库,授权

登录MySQL&#xff08;使用管理员账户&#xff09; mysql -u root -p 设置用户 -- 创建用户并设置密码 CREATE USER user_name% IDENTIFIED BY user_password;-- 删除用户 drop user user_name; 设置数据库 -- 创建数据库 CREATE DATABASE database_name;-- 删除数据库 DR…...

【洛谷算法题】P5712-Apples【入门2分支结构】

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5712-Apples【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格式&…...

vue项目中的js文件使用vuex

使用场景&#xff1a;假设有一个接口&#xff0c;需要在很多页面获取一遍并且将接口的返回值保存起来&#xff0c;这样就能使用vuex&#xff0c;将值保存在vuex中 实现&#xff1a;vuex中新建firmModule.js文件&#xff0c;编写存储值的代码&#xff0c;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是一款免费的思维导图软件&#xff0c;适用于Mac电脑用户。它可以帮助你轻松创建、编辑和共享思维导图&#xff0c;让你的思维更加清晰、有条理。 首先&#xff0c;Mindomo Desktop for Mac具有直观易用的界面。它采用了Mac独特的用户界面设计&#xf…...

Spark资源规划-资源上线评估

1、总体原则 以单台服务器 128G 内存&#xff0c;32 线程为例。 先设定单个 Executor 核数&#xff0c;根据 Yarn 配置得出每个节点最多的 Executor 数量&#xff0c;每个节点的 yarn 内存/每个节点数量单个节点的数量 总的 executor 数单节点数量*节点数。 2、具体提交参数 …...

RT-Thread STM32F407 定时器

定时器简介 硬件定时器一般有 2 种工作模式&#xff0c;定时器模式和计数器模式。不管是工作在哪一种模式&#xff0c;实质都是通过内部计数器模块对脉冲信号进行计数。下面是定时器的一些重要概念。 计数器模式&#xff1a;对外部输入引脚的外部脉冲信号计数。 定时器模式&…...

C#asp.net考试系统+sqlserver

C#asp.net简易考试系统 sqlserver在线考试系统学生登陆 判断学生是否存在 选择课程名 科目 可以进行答题操作&#xff0c;已经考试的课程不能再次答题&#xff0c; 自动根据课程名对应的题库生成试卷界面 加入选项类容 说明文档 运行前附加数据库.mdf&#xff08;或sql生成数…...

mac上配置maven

本文简述mac book上的Maven环境配置&#xff0c;着重讲述不同点。 1.安装 下载解压后&#xff0c;首先配置环境变量。编辑~/.bash_profile文件。加入如下代码&#xff1a; export M2_HOME/Users/jackie/tools/apache-maven-3.8.1注意&#xff1a;“/Users/jackie/tools/apac…...

解决vue-cli node-sass安装不成功问题

在项目中安装 vue-cli node-sass不成功解决办法如下&#xff1a; npm install node-sass --save 若以上方式安装不成功&#xff08;安装超时&#xff09;, 则使用以下的方法&#xff1a; 1. npm install -g cnpm --registryhttps://registry.npm.taobao.org 2. cnpm in…...

【Mysql】Mysql内置函数介绍

&#x1f308;欢迎来到Python专栏 &#x1f64b;&#x1f3fe;‍♀️作者介绍&#xff1a;前PLA队员 目前是一名普通本科大三的软件工程专业学生 &#x1f30f;IP坐标&#xff1a;湖北武汉 &#x1f349; 目前技术栈&#xff1a;C/C、Linux系统编程、计算机网络、数据结构、Mys…...

【Linux】vscode远程连接ubuntu失败

VSCode远程连接ubuntu服务器 这部分网上有很多&#xff0c;都烂大街了&#xff0c;自己搜吧。给个参考连接&#xff1a;VSCode远程连接ubuntu服务器 注意&#xff0c;这里我提前设置了免密登录。至于怎么设置远程免密登录&#xff0c;可以看其它帖子&#xff0c;比如这个。 …...

如何设计开发一对一交友App吸引更多活跃用户

在当今社交媒体时代&#xff0c;一对一交友App开发正日渐成为发展热点。如何吸引更多活跃用户成为开发者们的首要任务。通过本文&#xff0c;我们将探讨一系列方法&#xff0c;助您设计开发一对一交友App&#xff0c;吸引更多用户的关注和参与&#xff0c;提升App的活跃度。 了…...

UE基础篇六:音频

导语: 通过实现一个小游戏,来学会音频,最后效果 入门 下载启动项目并解压缩。通过导航到项目文件夹并打开SkywardMuffin.uproject来打开项目。 按播放开始游戏。游戏的目标是在不坠落的情况下触摸尽可能多的云。单击鼠标左键跳到第一朵云。 游戏很放松,不是吗?为了强调…...

vscode+python开发之虚拟环境和解释器切换

需求情景&#xff1a; 现在我们要开发多个项目比如&#xff1a;项目A&#xff0c;项目B、项目C&#xff0c;他们每个项目需要依赖不同的库。每个项目依赖的解释器也不一样怎么办&#xff1f; 项目A&#xff1a;需要在python3.7环境运行 依赖aadd3.2库 项目B、需要在python3.11…...

vite 样式按需加载

用于按需引入组件库样式的插件。 vite-plugin-impvite-plugin-style-import 以上两个插件可以实现按需引入组件库样式&#xff0c;尝试后发现vite-plugin-imp这个插件目前有个问题是&#xff0c;它支持按照组件动态引入组件内部的样式&#xff0c;但是antd还定义了一些全局样…...

Flutter打包iOS过程中pod访问github失败

问题描述 执行Flutter打包iOS命令出现如下错误&#xff1a; # 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博客...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)

一、OpenBCI_GUI 项目概述 &#xff08;一&#xff09;项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台&#xff0c;其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言&#xff0c;首次接触 OpenBCI 设备时&#xff0c;往…...