【翻译】6.824 lab1 (自用不负责)
简单记录一下,方便自己查看
开始实验
先用git下载实验的代码框架
$ git clone git://g.csail.mit.edu/6.824-golabs-2020 6.824
它提供的src/main/mrsequential.go
是一个顺序mapreduce实现,在单进程中执行map和reduce操作1次。
mrapps/wc.go
和mrapps/indexer.go
是两个MapReduce应用。
举例运行wc.go
$ cd ~/6.824
$ cd src/main
$ go build -buildmode=plugin ../mrapps/wc.go
$ rm mr-out*
$ go run mrsequential.go wc.so pg*.txt
$ more mr-out-0
A 509
ABOUT 2
ACT 8
...
mrequential.go
将其输出保留在文件mr-out-0
中。 它的输入来自名为pg-xxx.txt的文本文件。
可以随意从mrequential.go借用代码。
任务
实现一个分布式MapReduce,它由两个程序(master程序和worker程序)组成。
它将只有一个master进程以及一个或多个并行执行的worker进程。
在真实系统中,工作人员将在多台不同的机器上运行,但在本实验中,将在一台机器上运行它们。
worker通过RPC远程调用与Master对话。
每个Worker进程将向Master进程请求一个任务,从一个或多个文件读取任务的输入,执行任务,并将任务的输出写入一个或多个文件。
如果一个Worker没有在合理的时间内完成任务(本实验规定10秒),Master应该将该任务交给另一个Worker。
Master和Worker的main例程在main/mrmaster.go
和main/mrworker.go
中,不要改动这些程序。
需要在mr/master.go
,mr/worker.go
和mr.rpc.go
中实现自己的代码。
举例在单词统计wc.go
这个MapReduce应用程序上运行代码:
- 当前在main目录下,需要确保word-count插件是新构建的:
$ go build -buildmode=plugin ../mrapps/wc.go
-删除原来的输入(可能不存在),执行master代码
$ rm mr-out*
$ go run mrmaster.go pg-*.txt
- 在多个窗口中运行worker代码
$ go run mrworker.go wc.so
- 当worker和master都完成,在
mr-out-xxx
查看输出。输出文件的排序并集应与顺序输出匹配,用cat命令查看
$ cat mr-out-* | sort | more
A 509
ABOUT 2
ACT 8
...
在main/test-mr.sh
中有一个测试脚本,测试在给定pg-xxx.txt文件作为输入的情况下,检查wc和indexer MapReduce应用程序是否产生正确的输出。
这些测试还检查自己的实现是否并行运行Map和Reduce任务,以及Worker能否在运行任务崩溃时恢复。
如果现在直接运行测试脚本,他将会一直运行,因为master死循环。
$ cd ~/6.824/src/main
$ sh test-mr.sh
*** Starting wc test.
可以在mr/master.go
的Done函数中更改ret:=false
为ret:=true
,master就会立即结束。
$ sh ./test-mr.sh
*** Starting wc test.
sort: No such file or directory
cmp: EOF on mr-wc-all
--- wc output is not the same as mr-correct-wc.txt
--- wc test: FAIL
$
测试脚本期望在名为MR-OUT-X的文件中看到输出,每个Reduce任务对应一个文件。
mr/master.go和mr/worker.go的空实现不会生成这些文件(或执行许多其他操作),因此测试失败。
完成后,测试脚本输出应如下所示:
$ sh ./test-mr.sh
*** Starting wc test.
--- wc test: PASS
*** Starting indexer test.
--- indexer test: PASS
*** Starting map parallelism test.
--- map parallelism test: PASS
*** Starting reduce parallelism test.
--- reduce parallelism test: PASS
*** Starting crash test.
--- crash test: PASS
*** PASSED ALL TESTS
$
Go RPC软件包可能会有一些类似如下的提示,忽略这些信息
rpc.Register: method "Done" has 1 input parameters; needs exactly three
一些规则:
-
map阶段应将中间键划分为用于
nReduce
reduce任务的存储桶,其中nReduce
是main/mrmaster.go
传递给MakeMaster()
的参数。 -
Worker实现应将第X个reduce任务的输出放在文件mr-out-X中。
-
一个
mr-out-X
文件的每个Reduce函数输出应包含一行。 以Go中“%v%v”格式输出键和值。 在main/mrsequential.go
中查看注释为“这是正确的格式”的行。 如果偏离此格式太多,则测试脚本将失败。 -
可以修改mr/worker.go、mr/master.go和mr/rpc.go。可以临时修改其他文件进行测试,但请确保使用原始版本进行最终测试。
-
worker应该将中间映射输出放在当前目录中的文件中,这样稍后worker可以将它们读取他们作为Reduce任务的输入。
-
main/mrmaster.go
期望mr/master.go
实现Done()方法,该方法在MapReduce作业完全完成时返回true,结束mrmaster.go程序。 -
作业完全完成后,Worker进程应退出。一种简单的实现方法是使用call()的返回值:如果Worker进程无法联系Master进程,则可以假定Master进程已经退出,因为任务已经完成,因此worker进程也可以终止。根据该设计,Master可以交给Worker的“请退出”的伪任务会很有帮助。
提示
-
开始任务的一种方法是修改
mr/worker.go
的worker()
,以便向Master发送请求任务的RPC。然后修改master以响应一个尚未启动的映射任务的文件名。然后修改Worker以读取该文件并调用应用程序Map函数,如mrequential.go
中所示。 -
使用Go插件包在运行时从名称以.so结尾的文件中加载应用程序Map和Reduce函数。
-
如果更改了
mr/
目录中的任何内容,则可能需要使用类似于go build-buildmode=plugin../mrapps/wc.go
的命令重新构建MapReduce插件。 -
本实验的worker依赖于共享文件系统。 当所有worker在同一台机器上运行时,这很简单,但是如果worker运行在不同的机器上,则需要GFS这样的全局文件系统。
-
中间文件的合理命名约定是mr-X-Y,其中X是Map任务编号,Y是Reduce任务编号。
-
worker的map任务代码将需要一种方法来存储文件中的中间键/值对,这种方法可以在reduce任务期间正确读取。一种可能是使用Go的encoding/json包。要将键/值对写入JSON文件,请执行以下操作:
enc := json.NewEncoder(file)
for _, kv := ... {
err := enc.Encode(&kv)
要读回这样的文件,请执行以下操作:
dec := json.NewDecoder(file)
for {
var kv KeyValue
if err := dec.Decode(&kv); err != nil {
break
}
kva = append(kva, kv)
}
-
Worker的map部分可以使用
ihash(Key)
函数(在worker.go中)为给定的键选择Reduce任务。 -
可以从
mrequential.go
窃取一些代码,用于读取Map输入文件,对Map和Reduce之间的中间键/值对进行排序,以及在文件中存储Reduce输出。 -
作为RPC服务器的master将是并发的;不要忘记锁定共享数据。
-
使用Go的race检测器,与
go build -race
和go run -race
一起使用。test-mr.sh
的注释展示了如何为测试启用race检测器。 -
worker有时需要等待,例如 在最后一个map任务完成之前,reduce无法开始。一种可能是worker定期向master请求工作,在每次请求之间用
time.Sleep()
休眠。另一种方法是,Master中的相关RPC处理程序有一个等待的循环,可以是time.Sleep()
,也可以是sync.Cond
。GO在其自己的线程中为每个RPC运行处理程序,因此一个处理程序正在等待的事实不会阻止主处理程序处理其他RPC。 -
Master无法可靠地区分崩溃的worker,活着的但由于某种原因停工的worker和执行但速度太慢而无法使用的worker。可以让master等待一段时间,然后放弃并将任务重新分配给不同的worker。对于本实验,让master等待10秒,之后,master应该假定工人已经死亡(当然,它可能没有死)。
-
要测试崩溃恢复,可以使用mrapps / crash.go应用程序插件。 它在Map和Reduce函数中随机退出。
-
为了确保在崩溃时没有人观察到部分写入的文件,MapReduce的论文提到了使用临时文件并在完全写入后自动重命名的技巧。可以使用
ioutil.TempFile
创建临时文件,使用os.Rename
自动重命名它。 -
test-mr.sh
运行子目录mr-tmp`中的所有进程,因此,如果出现问题,并且希望查看中间文件或输出文件,请在此处查找。