本篇博文记录了我的lab1实现原理,思路以及答案。希望对大家有所帮助,也希望大家踊跃的指出错误和欢迎提出更好的思路算法。共勉。
前言
首先在做本实验之前,必须先阅读mapReduce论文
《MapReduce: Simplified Data Processing on Large Cluster 》
能看懂英文原版的当然看英文最好,看不懂的网上也有很多翻译版,大家自行查阅。可能翻译版都是靠翻译软件翻译的,很多地方有逻辑语义错误,不过问题不大,只是读起来别扭,看懂应该没问题的。
实验解析
论文我就不说了,不是本文的重点,本文重在讲解实验。
实验0 实验准备
做实验之前要先把官方提供的实验代码下载下来
具体下载方法实验指导书上面也写的很详细。大家按着提示下载就行了
$ git clone git://g.csail.mit.edu/6.824-golabs-2018 6.824
$ cd 6.824
实验一 映射/减少输入和输出
本实验完成common_map.go中的doMap()函数和 common_reduce.go中的doReduce()这两个函数。
doMap管理一个映射任务:它应该读取一个输入文件(inFile),为该文件的内容调用用户定义的映射函数(mapF),并将mapF的输出划分为nReduce中间文件。也就是说doMap的任务是把输入文件的内容分成一个一个的键值对然后进行输出
每个reduce任务有一个中间文件。文件名包含map任务编号和reduce任务编号。需要用到官方提供的
reduceName(jobName, mapTask, r)生成的文件名作为reduce任务r的中间文件,这个r如何取值呢?官方提供了一个ihash函数,将每个key传入ihash函数,返回一个int,最后再用此int mod nReduce就可以了。
还有一点就是由于reduce的输出必须是json格式,为了方便起见,这里的输出文件最好也输出为json格式(非必须)
func doMap(
jobName string, // the name of the MapReduce job
mapTask int, // which map task this is
inFile string,
nReduce int, // the number of reduce task that will be run ("R" in the paper)
mapF func(filename string, contents string) []KeyValue,
) {
// 打开输入文件
file,err:=os.OpenFile(inFile,os.O_RDONLY,0644)
if err!=nil {
fmt.Println("map 66文件打开失败:",err)
}
//记得关闭文件
defer file.Close()
//文件内容读取操作
reader:=bufio.NewReader(file)
FileContent,err1:=ioutil.ReadAll(reader)
if err1!=nil {
fmt.Println("map 74 文件打开失败:",err1)
}
ReduceKeyValue:=mapF(inFile,string(FileContent))
//生成reduce中间文件
for i:=0;i<nReduce;i++{
//中间文件命名规则 由项目提供的函数命名
RName:=reduceName(jobName,mapTask,i)
mapOutFile,err2:=os.OpenFile(RName,os.O_CREATE|os.O_WRONLY|os.O_APPEND,0644)
if err2!=nil{
fmt.Println(RName,"map 82 文件打开失败",err2)
}
//写入文件 使用json格式
enc:=json.NewEncoder(mapOutFile)
for _,value:=range ReduceKeyValue{
if ihash(value.Key)%nReduce==i {
err3:=enc.Encode(&value)
if err3!=nil {
fmt.Println<