Mit 6.824 lab1 MapReduce 设计

592 阅读4分钟

课程概述

这个课程的目的是让我们实现一个MapReduce,如果对MapReduce的基础概念不清楚,建议先看一下:

因 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 这三个文件

分析一下 ,我们要设计一下要点:

  1. Master 和 Wokrer 的 RPC 通信流程设计。

  2. Master 要记录task的处理情况

a. 分配给worker a的task不能再分配给worker b。

b. 如果 worker a 完成 task,则task不能再进行分配。

  1. Worker 可能有失败的情况,Master 需要进行 Worker 的故障处理。

  2. Master 的所有task都完成后,要exit(),设计 Master.Done() 方法

  3. 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 是任务管理者的角色,这里的管理主要有三件事

  1. 记录每个任务的执行状态

  2. 记录所有任务的整体情况

  3. 决定如何分配任务

抽象出一个任务的类似 task,负责表示每一个任务,然后任务的集中化管理使用taskPoll类进行封装。

这样master调用taskPoll的方法进行管理就好了。

taks的state有3种:

  1. ready : 表示初始化状态

  2. running: 该任务已被获取,正在执行中

  3. 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

解决办法:

  1. 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版本

  1. studygolang.com/dl 下载课程需要的1.13.6

  2. 下载,然后安装

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

然后就可以了.