MIT 6.5840(1) - Introduction

重生之我要学习分布式系列第一篇。

课程主页：

6.5840 Schedule: Spring 2024

明星课程 MIT 6.5840: Distributed Systems，原名 6.824，在 2024 年一共布置了 5 个 lab。这几个 lab 循序渐进，从古法分布式 MapReduce 搓起，然后手搓 raft，并最终造出类似 TiKV 的分布式数据库，整个过程做下来真有种开局一根针手搓 Windows 的爽感。

如何防治劲椎病

就像某国产 3A 大作的九九八十一难的第一难是解压游戏，本课程的第一难是让人憋出劲椎病的文档网页。

由于文档弹道偏左，考虑在控制台里把它水平居中。

Copy
const body = document.body;
body.style.maxWidth = "800px";
body.style.marginLeft = "auto";
body.style.marginRight = "auto";
const elements = body.getElementsByTagName("*");
for (let i = 0; i < elements.length; i++) {
elements[i].style.maxWidth = "100%";
elements[i].style.boxSizing = "border-box";
}

lab 内容简单介绍

lab1 是比较独立的开胃小菜，要实现一个 Google 曾经使用的 MapReduce 框架。

lab2 实现一个简单的单体 KV 服务器，要求在网络不稳定的情况下也能保证服务不出错。

lab3 则是实现 Raft 协议。

lab4 要基于 lab3 实现的 Raft 协议，构建一个 KV 服务器集群，也就是在 lab2 的基础上用 Raft 协议保证 Fault-tolerant。

lab5 则要在 lab4 的基础上，把数据库的数据分为几个分片（shard）来减轻单个服务器负担，需要实现他们的数据迁移。

个人认为最难实现的两个 lab 显然是 lab3 和 lab5。lab3 需要对 Raft 的原始论文仔细研读，lab5 则需要一开始就设计好整个架构如何实现，辅以网上搜索相关的实现思路才好开始上手。

Debug 小技巧

个人认为实现这些 lab 最有挑战性的地方不是在设计或者编写上，而是 debug 上。因为传统的打断点 debug 方法是对一个单体应用操作，而本次 lab 需要面对的是一个集群系统，打断点的方法就很难操作，所以主要还是靠 print 大法。那么设计一个好的打印函数非常有必要，例如可以把打印函数抽象出来。例如 lab5 我用了这样一个函数对 println 包装

Copy
func (kv *ShardKV) SSPrintf(format string, a ...interface{}) (n int, err error) {
if SDebug {
log.Printf("[server %d]"+format, append([]interface{}{kv.gid}, a...)...)
}
return
}

kv.gid 是标识 ShardKV 的相关信息之一，实践上还可以塞入更多的基本信息，当然这可能要考虑获取这些信息会不会造成读写上的条件竞争的问题。

本次实验我只用了 SDebug 来判断是否打印日志，但实际上可以设计一个类似 level 的东西，来方便区分重要日志和不那么重要的日志。

在需要分析 Bug 日志的时候，可以借助 Linux 的 tee 命令让日志同时输出到 stdout 和文件里。

Copy
go test -race -run TestConcurrent3_5B | tee bug.txt

在需要输出日志的地方可以多加几个条件判断，确认是 bug 可能发生的那种条件，这样可以减少大量无意义的日志。

代码仓库

KingBridgeSS/MIT-6.5840: My solution for labs in MIT-6.5840 (https://pdos.csail.mit.edu/6.824/)