前言
2019 年暑假在「Face++」云平台部门实习,从事基于分布式系统的研发,组内推荐完成 6.824,我也觉得很有必要系统地巩固这方面知识,便计划两个月内完成这门课。
由于课程开头说明了 Please do not publish your code or make it available to current or future 6.824 students.
,在文章里我不会贴代码,只记录我实现的方法和遇到的坑,如果对实验有什么疑问,欢迎一起讨论。
6.824 - Spring 2018 Lab 1: MapReduce
Part I: Map/Reduce input and output
doMap 函数先创建 nReduce 个文件,mapF 函数算出所有 kv,把内容 json 编码放入相应文件。
doReduce 函数从每个 doMap 输出给目前 reduceTask 的文件 json 解码读出来,维护一个 map[string][]string
结构保存每个 key 对于的 values,json 编码输出到 outFile。
⚠️ 注意 json 编码相关的两个函数 Encode 和 Decode 接受的是指针。
Part II: Single-worker word count
可以对文章的每个词分别返回 <word, 1>
,也可以用一个 map[string]int
记录每个词出现次数再返回。
Part III: Distributing MapReduce tasks
我用了 Go 语言的 channel
和 sync.WaitGroup
,前者用于把 ntasks 个任务传递给 worker,后者用于判断是否所有 worker 都工作完了,wg.Wait()
过后才退出 schedule 函数。
⚠️ registerChan 居然不会 close,为此使用一个新的 channel 用来标记任务是否已经分发完,如果从这个管道获得信号,便停止从 registerChan 读 worker。
Part IV: Handling worker failures
在上一部分基础上改进,如果 call()
函数返回的是 true,让 worker 继续做新的任务;如果返回 false,那么需要把这个未完成的任务放回任务池(数据结构是 channel
),并且放弃这个 worker(wg.Done()
)。难点在于确定 worker 真正工作完的时间,就是:
- 所有任务都分发出去了
- 没有正在运行的执行任务的 worker
上一部分已经解决了 1,对于 2,我新建一个整数变量作为计数器,记录正在执行任务的 worker 数量,使用 atomic.LoadInt32
和 atomic.AddInt32
进行读写。
看来这个部分需要熟悉 Go 语言才会做得没那么吃力。。
Part V: Inverted index generation (optional)
感觉没什么难度,mapF 函数里用 map[string]bool
维护文档的单词集合。