Lab1 MapReduce
简谈mr
mr的出现就是因为单机无法处理过多的任务,需要多加几台机器来提高性能,那么就要处理多台机器的分工合作问题。拿word-count举例,将任务均分到集群中的每台机器,各自运算得出结果,再将结果收集进行合并,这个过程就是mapreduce。
分布式的机器处理时是并行的,互相不影响,对比单机能提升几倍的性能,但是过多的机器会导致机器间通信效率的降低,并且容易出现机器崩溃。
论文和作业
论文介绍的mr是非常全面的(模型、实现技巧、性能提升),而且是站在多集群的角度说明问题,真正的mr需要分布式的文件系统进行存储,显然我们不具备这样的实验环境,所以lab1的作业是单机的,实现一个简单的mr模型,并具备处理worker crash、worker并发执行的能力。
假设你已经读过论文和作业文档,接下来说一下设计和实现mr模型的细节:
- mr模型的第一步骤就是master启动,去通知worker开始执行任务。lab提示,可以通过worker向master请求任务的方式实现。通过rpc请求master的任务调度函数。
- master此时要处理多个worker的并发请求,因此必须对共享资源加锁。保证每个worker得到的任务不会重复。
- master可以将任务加入循环队列,如果队列为空,可能是所有任务执行结束,也可能是有的任务timeout或crash,那么找到未完成的任务并将其加入队列即可。
- 可能某个worker只是timeout,master已经将其持有的任务重新分发,当worker执行结束返回结果时,master要忽略该结果。
- map阶段worker要执行的是:
- 读取文件,通过map解析出n个
- 将这n个键值对hash到nReduce个文件中,可以使用ihash(key) % nReduce。
- 一个worker产生nReduce个临时文件,写入完成后通过rpc通知master更新任务状态。
- reduce阶段worker要执行的是:
- 读取临时文件,一个reduce worker要读取X个文件。
- 读取的数据进行排序,然后输出为mr-out-Y文件,此处可以参考mrsequence.go。
- 写入完成后,通知master更新任务状态。
- master在第3步,判断队列为空的原因是任务都完成,那么可以结束任务,将Done函数的返回值变为true即可。
- worker不知道master已经退出,rpc返回false,worker也退出即可。
一些坑
- 将6.824clone下来后,不要使用go mod init,直接在代码里操作。如果导包有问题,就更换为"../mr",使用相对路径即可。
- 自己调试时,每次都需要build一下插件,然后启动master,再启动worker。插件就是用户自定义的map和reduce函数,使用插件可以将函数嵌入到mr流程。
- 测试最终结果时,直接运行test-mr.sh即可,测试脚本会启动多个worker线程,测试worker多线程并发、worker crash等情况。
- 打印的日志最好统一格式,带上pid。
- mac没有timeout命令,需要下载并替换成gtimeout。
ps:已通过test-mr.sh,若需要代码,请在下方评论。