├── .gitignore ├── Makefile ├── README.md ├── StudyNotes ├── 第一节:Introduction_MapReduce_Lab1.md ├── 第三节:GFS.md ├── 第二节:RPC&threads.md └── 第四节:主从复制.md ├── image ├── LAB1_Pass.jpg └── mapreduce.jpg └── paper ├── Fault-Toleranr-Virtual-Machines.pdf ├── gfs.pdf ├── mapreduce.pdf └── raft.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | mr-* 3 | mr-out* 4 | mr-tmp* 5 | *.so 6 | .idea 7 | src/* 8 | MIT* -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # This is the Makefile helping you submit the labs. 2 | # Just create 6.824/api.key with your API key in it, 3 | # and submit your lab with the following command: 4 | # $ make [lab1|lab2a|lab2b|lab2c|lab3a|lab3b|lab4a|lab4b] 5 | 6 | LABS=" lab1 lab2a lab2b lab2c lab3a lab3b lab4a lab4b " 7 | 8 | %: check-% 9 | @echo "Preparing $@-handin.tar.gz" 10 | @if echo $(LABS) | grep -q " $@ " ; then \ 11 | echo "Tarring up your submission..." ; \ 12 | tar cvzf $@-handin.tar.gz \ 13 | "--exclude=src/main/pg-*.txt" \ 14 | "--exclude=src/main/diskvd" \ 15 | "--exclude=src/mapreduce/824-mrinput-*.txt" \ 16 | "--exclude=src/main/mr-*" \ 17 | "--exclude=mrtmp.*" \ 18 | "--exclude=src/main/diff.out" \ 19 | "--exclude=src/main/mrmaster" \ 20 | "--exclude=src/main/mrsequential" \ 21 | "--exclude=src/main/mrworker" \ 22 | "--exclude=*.so" \ 23 | Makefile src; \ 24 | if ! test -e api.key ; then \ 25 | echo "Missing $(PWD)/api.key. Please create the file with your key in it or submit the $@-handin.tar.gz via the web interface."; \ 26 | else \ 27 | echo "Are you sure you want to submit $@? Enter 'yes' to continue:"; \ 28 | read line; \ 29 | if test "$$line" != "yes" ; then echo "Giving up submission"; exit; fi; \ 30 | if test `stat -c "%s" "$@-handin.tar.gz" 2>/dev/null || stat -f "%z" "$@-handin.tar.gz"` -ge 20971520 ; then echo "File exceeds 20MB."; exit; fi; \ 31 | mv api.key api.key.fix ; \ 32 | cat api.key.fix | tr -d '\n' > api.key ; \ 33 | rm api.key.fix ; \ 34 | curl -F file=@$@-handin.tar.gz -F "key= /dev/null || { \ 36 | echo ; \ 37 | echo "Submit seems to have failed."; \ 38 | echo "Please upload the tarball manually on the submission website."; } \ 39 | fi; \ 40 | else \ 41 | echo "Bad target $@. Usage: make [$(LABS)]"; \ 42 | fi 43 | 44 | .PHONY: check-% 45 | check-%: 46 | @echo "Checking that your submission builds correctly..." 47 | @./.check-build git://g.csail.mit.edu/6.824-golabs-2020 $(patsubst check-%,%,$@) 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MIT-6.824-2020 2 | 学习 MIT-6.824 过程中进行的总结成果 3 | 4 | # 资源 5 | YouTube: [https://www.youtube.com/watch?v=cQP8WApzIQQ](https://www.youtube.com/watch?v=cQP8WApzIQQ) 6 | 7 | Bilibili: [https://www.bilibili.com/video/av87684880?from=search&seid=17285044581056449164](https://www.bilibili.com/video/av87684880?from=search&seid=17285044581056449164) 8 | 9 | 课程 schedule: [http://nil.csail.mit.edu/6.824/2020/schedule.html](http://nil.csail.mit.edu/6.824/2020/schedule.html) 10 | 11 | 通过 schedule 可以获得包括课件,实验,源码,Q&A 等一系列资源,这里不进行列举。 12 | 13 | # 课程笔记列表 14 | 15 | 1. [Introduction_MapReduce_Lab1](https://github.com/nercoeus/MIT-6.824-2020-Distributed-Systems/blob/master/StudyNotes/%E7%AC%AC%E4%B8%80%E8%8A%82:Introduction_MapReduce_Lab1.md) 16 | 2. [golang RPC & threads](https://github.com/nercoeus/MIT-6.824-2020-Distributed-Systems/blob/master/StudyNotes/%E7%AC%AC%E4%BA%8C%E8%8A%82:RPC%26threads.md) 17 | 3. [GFS](https://github.com/nercoeus/MIT6.824-2020-Distributed-Systems/blob/master/StudyNotes/%E7%AC%AC%E4%B8%89%E8%8A%82:GFS.md) 18 | 19 | # 论文列表(带笔记) 20 | 21 | 1. [MapReduce](https://github.com/nercoeus/MIT-6.824-2020-Distributed-Systems/blob/master/Documents/mapreduce.pdf) 22 | 23 | 24 | # 实验情况(根据课程要求暂时不提供实验代码,有需要可以联系本人获取当前进度代码) 25 | 26 | 1. Lab1: MapReduce PASS ALL 27 | 2. Lab2: PASS 2A 28 | 29 | # 参考资料 30 | 31 | 1. [Students' Guide to Raft](https://thesquareplanet.com/blog/students-guide-to-raft/) 32 | 2. [Raft 动画演示](http://thesecretlivesofdata.com/raft/) 33 | -------------------------------------------------------------------------------- /StudyNotes/第一节:Introduction_MapReduce_Lab1.md: -------------------------------------------------------------------------------- 1 | # 内容 2 | 3 | 什么是分布式系统? 4 | * 多台协作的机器 5 | * 大型网站的存储,大数据的计算:MapReduce,p2p 分享 6 | * 分布式的管理多个基础架构 7 | 8 | 为什么要使用分布式系统? 9 | * 高性能 10 | * 因为物理上的原因不得不使用分布式架构(两家物理机不在一起但是需要一起提供某一服务) 11 | * 通过复制提高可用性(容错性) 12 | * 通过隔离保证可靠性 13 | 14 | 分布式系统的挑战: 15 | * 分布式系统的构建十分复杂 16 | * 需要应对部分组件的错误 17 | * 难以发挥机器的性能(并不是 1000 台计算机就会有 1000 倍的性能) 18 | 19 | Topic: 20 | - 分布式系统的基础组件:RPC通信,线程机制,并发控制 etc 21 | - 高性能:横向扩展,同时也需要实现负载均衡,处理逻辑并发,共享资源瓶颈等等问题 22 | - 容错行:随着计算机数量的升级会频繁的出现程序或者集群节点的崩溃 23 | - 可用性 24 | - 可恢复性 25 | - 一致性:弱一致性和强一致性 26 | 27 | # 案例研究:mapReduce 28 | ## 概述 29 | context:将大数据下的耗时计算操作分散到多台机器上进行计算 30 | 总体目标:初级程序员简单的顺序调用 Map 和 Reduce 方法完成数据操作,并发的细节被隐藏掉了 31 | ## MapReduce 抽象视图 32 | Input* 是整个计算的输入,可能是大量的待计算数据等. 使用 Map function 来计算大量数据中的一小部分,最后将所有 Map 计算的结果使用 Reduce function 来进行收集并统计结果输出. 33 | ``` 34 | Input1 -> Map -> a,1 b,1 35 | Input2 -> Map -> b,1 36 | Input3 -> Map -> a,1 c,1 37 | | | | 38 | | | -> Reduce -> c,1 39 | | -----> Reduce -> b,2 40 | ---------> Reduce -> a,2 41 | ``` 42 | 讲义中 MapReduce 的例子 43 | 通过调用 Map() 为每个出入文件产生一组 k2,v2 44 | 并通过 Reduce() 收集上面产生的 k,v 最后输出处理结果 45 | ## MapReduce 有很好的横向扩展性 46 | Map()s 和 Reduce()s 方法可以在互不影响的情况下并行运行,所以可以很容易的通过增加机器来提高的吞吐率 47 | ## MapReduce 隐藏了很多的细节 48 | * 将任务自动部署到机器集群上进行执行 49 | * 跟踪的任务直至完成 50 | * 控制 Map() 和 Reduce() 之间的数据传输 51 | * 机器间的负载均衡 52 | * 从失败中恢复 recover 53 | ## MapReduce 的限制 54 | * Map()s 和 Reduce()s 之间不可以相互作用也没有不同状态 55 | * 没有迭代以及多阶段的管道 56 | * 没有实时或者流式处理,只能根据预先制定好的 Map 和 Reduce 规则进行处理 57 | ## 为什么会限制性能 58 | 网络和cpu/磁盘会限制性能,在 MapReduce 中网络带宽是很大的阻碍,论文第 8 小结关于网络带宽的优化方法总结如下: 59 | 1. 将输入数据保存到不同的机器上并就近原则执行 Map 方法,即 Input 数据和 Map() 在同一台机器上减少网络操作节约性能. 60 | 2. 将生成的中间数据的一个副本保存在本地磁盘上,作用和上面的类似,可以就近执行 Reduce 操作.这种并不能避免所有的 Reduce() 的网络带宽. 61 | 62 | 但是发展到现在,其实网络带宽已经不是主要的问题了。 63 | # 论文 64 | 65 | 见 Documents 目录下的 MapReduce.pdf 了解更多和 MapReduce 相关知识。 66 | 67 | # 实验 68 | ![MapReduce 执行流程](https://github.com/nercoeus/MIT-6.824-2020-Distributed-Systems/blob/master/image/mapreduce.jpg) 69 | 上图是 MapReduce 的执行流程,这里实验代码实现也尽量参照上面的流程进行实现。实验代码见 src/MapReduce 目录。 70 | 71 | 自带的例子就不进行展示了:大概流程就是先将一系列的文件通过 Map() 函数进行解析为 {key:name,value:1} 的集合,然后在排序后并使用 Reduce() 统计相同词的频率然后统一写入输出文件即可。 72 | 73 | 需要我们实现一个分布式的 MapReduce,通过 RPC 进行通信工作进程向主进程请求任务,从一个文件或多个文件中读取输入,并将任务的输出写入到一个文件或多个中。主进程并监控如果从进程在一定时间内没有完成任务就需要切换一个进程执行任务。 -------------------------------------------------------------------------------- /StudyNotes/第三节:GFS.md: -------------------------------------------------------------------------------- 1 | # 内容 2 | 3 | ## 为什么读 GFS? 4 | 1. 分布式存储是分布式系统十分重要的使用方向 5 | - 怎么设计接口和语义 6 | - 内部应该怎么工作 7 | 2. 和课程主题相关:高性能,容错,复制(从服务器),一致性 8 | 3. 好的系统论文:详细描述了 apps 到 net 之间的细节 9 | 4. 成功的实现了这一设计并应用到工业界 10 | 11 | ## 为什么分布式存储很难实现? 可以参考 CAP 理论 12 | 1. 高性能 -> 在多个服务器之间共享数据 : 高性能就需要多台计算器,所以不同机器之间需要共享数据 13 | 2. 多服务器 -> 不间断的单点故障 : 机器一多,不可避免会有大量的故障 14 | 3. 频繁的节点故障 -> 复制 : 通过复制错误的机器的数据到正常机器上进行替换达到容错的目的 15 | 4. 复制 -> 不能很好地满足一致性 : 使用复制就会遇到相同内容不同机器不一致的问题 16 | 5. 好的一致性 -> 较差的性能 : 为了严格控制这种一致性就会降低性能 17 | 18 | ## 保证一致性? 19 | 理想情况下: 20 | 1. 分布式的服务就好像在同一个服务中一样,调用方并不需要考虑过多东西 21 | 2. 服务器使用磁盘进行存储 22 | 3. 服务器一次执行一个客户端的操作(即使并发情况下) 23 | 4. 会加载历史数据,当服务器崩溃重新启动后, GFS 应该仅仅会 master 节点加载元数据 24 | 25 | 26 | ## 通过从服务器来保证容错性很难保证强一致性 27 | 一个简单但是弱一致性的方案:两个从服务器,S1 和 S2。客户端会同时向这两个服务器写入,但只会从任意一个服务器读取。 28 | 如果客户端发送了 S1 的写入请求,但是在发送 S2 时崩溃,这样二者就不一致了。如果想要保证服务器之间的一致性,需要频繁的进行同步操作,这样的话就会影响性能。 29 | 所以需要在一致性和性能之间进行权衡。 30 | 31 | ## GFS 内容: 32 | 1. Google 中许多服务需要一个大型的快速统一的存储系统:MapReduce、网页爬虫/索引、日志存储分析系统、youtube? 等等 33 | 2. 全局(通过单个节点):任何用户可以读取系统中的任何文件。允许在应用之间共享数据 34 | 3. 自动故障恢复 35 | 4. 一个数据中心 36 | 5. 仅供 Google 的应用和用户进行使用 37 | 6. 目的在于大型文件的连续访问、读取或追加. 并不注重小字段的存储 38 | 39 | ## 整体架构 40 | 1. 大量的客户端(数据库,RPC) 41 | 2. 一个 master 节点和多个 chunk server 节点. master 来管理所有的 chunk 节点 42 | 3. 每个大文件拆分多个为 64MB 大小的块,可以保存在不同的 chunk 节点中 43 | 4. 每个块在三台 chunk 节点上进行备份。 44 | 45 | ## master 节点的元数据 46 | 1. 用来管理 chunk 信息的表 47 | 2. 用来记录每个 chunk 节点和其上的数据块之间的映射 48 | 3. log 文件,用来记录数据的变更,并会生成 checkpoint 用来恢复 master 节点(使用log记录会更加快速,而不是使用 b-tree 会存在寻找插入位置的过程导致较慢,有趣的角度) 49 | 50 | ## 客户端读取一个文件的步骤 51 | 1. client 发送文件名称和偏移量给主服务器 master 52 | 2. master 根据偏移量找到第一个需要的数据块的句柄 53 | 3. master 把保存了该数据块的 chunk 服务器列表发送给 client 54 | 4. client 缓存 chunk 服务器列表,用以多次重复访问 55 | 5. client 从最近的 chunk 服务器请求数据块 56 | 6. chunk 服务器从磁盘读取文件并返回给 client 57 | 58 | ## 如何保证 GFS 的强一致性:GFS 并没有实现,成本过于高昂 59 | 1. primary 节点需要过滤重复的写入请求,防止数据出现多次 60 | 2. 从节点必须正确执行 primary 节点给与的任务 61 | 3. 使用两阶段提交保证任务被每个节点成功执行了 62 | 63 | ## GFS 存在的缺陷 64 | 1. 只有一个 master 节点,并且不支持自动回复,出错需要人工干预 65 | 2. 由于他可能会执行重复的追加操作,有些客户端不能很好地处理这种情况 66 | 3. 单个 master 节点需要处理大量的请求,这是很困难的 67 | # reference 68 | - 谈谈分布式系统的CAP理论:[https://zhuanlan.zhihu.com/p/33999708#:~:text=CAP%E7%90%86%E8%AE%BA%E6%A6%82%E8%BF%B0,%E9%A1%B9%E4%B8%AD%E7%9A%84%E4%B8%A4%E9%A1%B9%E3%80%82](https://zhuanlan.zhihu.com/p/33999708#:~:text=CAP%E7%90%86%E8%AE%BA%E6%A6%82%E8%BF%B0,%E9%A1%B9%E4%B8%AD%E7%9A%84%E4%B8%A4%E9%A1%B9%E3%80%82) 69 | - wiki:CAP theorem:[https://en.wikipedia.org/wiki/CAP_theorem](https://en.wikipedia.org/wiki/CAP_theorem) -------------------------------------------------------------------------------- /StudyNotes/第二节:RPC&threads.md: -------------------------------------------------------------------------------- 1 | # 内容 2 | 这一节了解一下 golang 中的 rpc 和 threads 3 | 4 | ## 为什么使用 go 来教学? 5 | - go 中有 goroutine,更容易使用的并发机制 6 | - 更加方便使用的 RPC 7 | - 类型安全 8 | - 提供 GC 机制 9 | - 相比于 c++, golang 更加简单易用 10 | 11 | ## golang 中的 goroutine(自行了解) 12 | 并发对分布式编程是十分重要的,并且 go 的 goroutine 是十分简单易用的。 13 | 稍微了解 go 的都知道其实 goroutine 是建立在系统线程上的一种机制,更加轻便,快速切换。 14 | 15 | ## 使用 thread 的原因 16 | I/O 并发:客户端发送多个请求给不同的服务器然后等待回复,服务器接收多个客户端的请求进行处理。等待磁盘读取的同时处理客户的请求。 17 | 多核性能:可以充分地利用多核的性能 18 | 方便一些实现:例如 master 循环的检查每个 worker 状态是否正常。 19 | 20 | ## thread 的替代方案: 21 | 在一个线程中使用事件循环机制,将所有事件存储起来,并不断地获取触发的事件并进行处理。redis 中有类似的操作。 22 | 23 | ## 使用 thread 的挑战: 24 | - 共享内存带来的冲突,可以加锁,或者使用 TLS 25 | - thread 之间的同步。golang 中推荐 channel 来进行同步,go 还提供了许多同步方式,sync 包中 26 | - 死锁 27 | 28 | ## 爬虫示例 29 | 课程后半段通过一个爬虫例子来分别展示了三种不同的方式实现了 Crawler。 30 | - 递归的进行爬取 31 | - 通过 goroutine + WaitGroup 的方式并发的实现 Crawler,并通过 Mutex + map 的方式防止爬取重复的 URL 32 | - 通过 channel 实现不同 goroutine 之间的同步,并使用 map 来防止重复的爬取,因为该 map 上的操作不涉及并发。 33 | 34 | # 总结一下 35 | 除了课程中的 Crawler,schedule 中还提供了一个 kv 例子使用了 RPC 机制,课上时间不够就没讲。这节课就讲了一下 goroutine 中的协程以及并发控制,同步方法。其中 Crawler 中实现的三种方式可以看一下,实现的很有特点。 36 | 简单介绍一下 KV 例子: 37 | 1. 启动服务端 38 | 2. 创建客户端,并和服务端建立 TCP 连接,然后调用 rpc 接口,底层通过 RPC 库的 Call 实现。 39 | 3. 服务器处理收到的请求,执行后返回即可,服务器使用 goroutine 执行每个新的连接上的调用,所以需要做一些 mutex 的操作。 40 | 41 | 但是使用 RPC 需要考虑很多的网络延迟、执行失败等等问题。真正在项目中使用 RPC 需要考虑的方方面面东西繁琐。不过面对一般的错误。可以最简单的设置超时,失败后客户端业务层进行处理,判断是重新执行,还是报错返回等等。 42 | -------------------------------------------------------------------------------- /StudyNotes/第四节:主从复制.md: -------------------------------------------------------------------------------- 1 | # 内容 2 | 3 | ## 通过复制可以解决那些类型的错误? 4 | 1. 单节点的 "fail-stop" 导致的出错 5 | - 各种各样的机器故障 6 | 2. 可能是因为程序编写错误或者是配置出错 7 | - 这一般不会导致停止运行,可校验的 8 | 3. 如果发生类似于地震或者大停电的情况 9 | - 可以将备份放在不同的物理机器上,例如多地的机房进行存储 10 | 11 | ## 两种复制的不同方式 12 | 1. 状态的转变 13 | 2. 复制状态机 14 | 15 | # reference 16 | -------------------------------------------------------------------------------- /image/LAB1_Pass.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nercoeus/MIT6.824-2020-Distributed-Systems/79b6771054c904bb1c765252673cd2ad7acef090/image/LAB1_Pass.jpg -------------------------------------------------------------------------------- /image/mapreduce.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nercoeus/MIT6.824-2020-Distributed-Systems/79b6771054c904bb1c765252673cd2ad7acef090/image/mapreduce.jpg -------------------------------------------------------------------------------- /paper/Fault-Toleranr-Virtual-Machines.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nercoeus/MIT6.824-2020-Distributed-Systems/79b6771054c904bb1c765252673cd2ad7acef090/paper/Fault-Toleranr-Virtual-Machines.pdf -------------------------------------------------------------------------------- /paper/gfs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nercoeus/MIT6.824-2020-Distributed-Systems/79b6771054c904bb1c765252673cd2ad7acef090/paper/gfs.pdf -------------------------------------------------------------------------------- /paper/mapreduce.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nercoeus/MIT6.824-2020-Distributed-Systems/79b6771054c904bb1c765252673cd2ad7acef090/paper/mapreduce.pdf -------------------------------------------------------------------------------- /paper/raft.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nercoeus/MIT6.824-2020-Distributed-Systems/79b6771054c904bb1c765252673cd2ad7acef090/paper/raft.pdf --------------------------------------------------------------------------------