一、实验说明
https://pdos.csail.mit.edu/6.824/labs/lab-1.html
二、梳理
在 lab1 中需要编写填充MapReduce 部分代码,使用 Go 建立一个容错的分布式系统。
mapreduce 包提供了一个简单的 Map/Reduce 库,调用 master.go/Distributed()
来开始任务
mapreduce在运行大致为5部分
1. input:获取输入数据进行分片作为map的输入
2. map:将输入记录解析成一条或多条记录
3. shuffle:对中间数据的处理,作为reduce的输入
4. reduce:对相同key的数据进行合并
5. output:按照格式输出到指定目录
代码主要流程如下:
- Master 读取输入文件,然后调用
common_map.go中的doMap()
。doMap()
运行 mapF (),将文件转化为 key/value (KeyValue)结果写入nReduce
个中间文件之中。在 map 结束后总共会生成nMap * nReduce
个文件。 - 之后调用
common_reduce.go/doReduce()
,doReduce()
将按照 reduce task 编号(reduceTask)来汇总,生成nReduce
个结果文件。
Master
doneChannel:无缓冲信道,用于判断是否完成(完成前堵塞)
newCond:条件锁,等待Register添加workers(forwardRegistrations())
workers:worker的RPC address
jobName:任务名称
files:Input文件
nReduce:reduce分区数
shutdown:是否停止(startRPCServer()),通过chan完成堵塞(mr.Wait())
l:监听器,监听“unix”
stats:shutdown后,获取worker的任务数
type Master struct {
sync.Mutex
address string
doneChannel chan bool
// protected by the mutex
newCond *sync.Cond // signals when Register() adds to workers[]
workers []string // each worker's UNIX-domain socket name -- its RPC address
// Per-task information
jobName string // Name of currently executing job
files []string // Input files
nReduce int // Number of reduce partitions
shutdown chan struct{}
l net.Listener
stats []int
}
run
- 两次schedule(map、reduce)
- finish()(结束任务,记录stats用作check)
- merge()合并文件
- doneChannel,无缓冲chan结束堵塞,执行mr.Wait()之后逻辑
func (mr *Master) run(jobName string, files []string, nreduce int,
schedule func(phase jobPhase),
finish func(),
) {
mr.jobName = jobName
mr.files = files
mr.nReduce = nreduce
fmt.Printf("%s: Starting Map/Reduce task %s\n", mr.address, mr.jobName)
schedule(mapPhase)
schedule(reducePhase)
finish()
mr.merge()
fmt.Printf("%s: Map/Reduce task completed\n", mr.address)
mr.doneChannel <- true
}
func RunWorker(MasterAddress st