课程概述
这个课程的目的是让我们实现一个MapReduce,如果对MapReduce的基础概念不清楚,建议先看一下:
-
课程官网网页 : nil.csail.mit.edu/6.824/2020/…
-
parper: pdos.csail.mit.edu/6.824/paper…
因 mit 课程要求,不能提供源码等信息,所以本文不提供具体的代码实现,而是说一说部分设计思路
课程中,我们是使用一台机器模拟出分布式的效果,通信使用RPC的方式,部署的方式是一个master + 多个worker。
-
master的主要任务就一个:分配task给worker
-
worker的主要任务有两个:1.向master请求task 2.判断 task 类型,使用map()或者reduce()执行。
简单的表示如下:

下面是详细的的要求解释:
- 整个 MR 框架由一个 Master 进程及若干个 Worker 进程构成
Master 进程与 Worker 进程间通过本地 Socket 进行 Golang RPC 通信
-
由 Master 协调整个 MR 计算的推进,并分配 Task 到 Worker 上运行
-
在启动 Master 进程时指定 输入文件名 及 Reduce Task 数量
-
在启动 Worker 进程时指定所用的 MR APP 动态链接库文件
-
Master 需要留意 Worker 可能无法在合理时间内完成收到的任务(Worker 卡死或宕机),在遇到此类问题时需要重新派发任务
-
Master 进程的入口文件为 main/mrcoordinator.go,Worker 进程的入口文件为 main/mrworker.go
-
我们需要补充实现 mr/master.go、mr/worker.go、mr/rpc.go 这三个文件
分析一下 ,我们要设计一下要点:
-
Master 和 Wokrer 的 RPC 通信流程设计。
-
Master 要记录task的处理情况
a. 分配给worker a的task不能再分配给worker b。
b. 如果 worker a 完成 task,则task不能再进行分配。
-
Worker 可能有失败的情况,Master 需要进行 Worker 的故障处理。
-
Master 的所有task都完成后,要exit(),设计 Master.Done() 方法
-
Worker 区分 Master 分配的任务类型,然后分配执行对应的方法
详细一些的图示如下:

设计实现
RPC通信
先给master添加个方法,直接在master.go下添加,例如这里要添加一个申请task的方法ApplyTask()
func (m *Master) ApplyTask(req *RpcReq, rep *RpcRep) error{
fmt.Printf("worker apply task,req %v ", req.ReqType)
rep.RepType = 1
return nil
}
这样就给master添加了一个新的方法,如何给worker进行rpc调用呢?Go 中非常方便,下面直接在worker#Worker()方法中添加
func Worker(mapf func(string, string) []KeyValue, reducef func(string, []string) string) {
req := RpcReq{ReqType: 2}
rep := RpcRep{}
// 方法名 + 方法参数
call("Master.ApplyTask",&req,&rep)
fmt.Printf("rep.repType %v \n",rep.RepType)
}
运行master和worker后,就可以看到对应的输出了。
Master
master 是任务管理者的角色,这里的管理主要有三件事
-
记录每个任务的执行状态
-
记录所有任务的整体情况
-
决定如何分配任务
抽象出一个任务的类似 task,负责表示每一个任务,然后任务的集中化管理使用taskPoll类进行封装。
这样master调用taskPoll的方法进行管理就好了。

taks的state有3种:
-
ready : 表示初始化状态
-
running: 该任务已被获取,正在执行中
-
done: 该任务已经完成,无法再获取
这样commit方法相当于把task的state从running -> done, rollback 相当于从running -> ready。
过期任务的检查
每一个task中保存开始执行的时间,taskPoll通过启动一个线程每秒进行一次检查,
当有发现某个task的执行时间超过10s时,就认为该task在worker中执行失败了,所以将该任务进行rollback,保证其他worker可以获取到该task。
worker

遇到的一些问题
编译失败1:
执行go build时,报错:
build command-line-arguments: cannot find module for path _/Users/xxx/xxx/6.824/src/mr
解决办法:
- GO111MODULE=off 禁用 go module
编译失败情况2:
在执行go build时,报错
/usr/local/go/pkg/tool/darwin_amd64/link: /usr/local/go/pkg/tool/darwin_amd64/link: combining dwarf failed: unknown load command 0x80000034 (2147483700)
解决办法:下载对应的go版本
-
在 studygolang.com/dl 下载课程需要的1.13.6
-
下载,然后安装

test-mr.sh: command not found
出现 test-mr.sh: line 40: timeout: command not found 这种语句 ,
看下第40行的代码,是一个timeout命令.
timeout -k 2s 180s ../mrmaster ../pg*txt &
timeou在mac上没有默认按照,所以要安装一下
brew install coreutils
然后就可以了.