本文是MapReduce论文的学习笔记。MapReduce框架须要使用者提供map和reduce函数,map函数将一个键/值输入转换成一组中间键/值,而后reduce函数将全部具备相同键的中间键值对进行合并,而其余的任务调度、文件分割、容错处理等工做都由框架来完成。编程
MapReduce框架用户须要提供两个函数map和reduce:app
初看很难体会到MapReduce的设计初衷,而MapReduce最经典的例子就是单词计数任务,单词计数任务的两个函数定义以下:框架
func map(filename string, contents string) []mapreduce.KeyValue {
words := strings.FieldsFunc(contents, func(r rune) bool {
return !unicode.IsLetter(r)
})
var res []mapreduce.KeyValue
for _, word := range words {
res = append(res, mapreduce.KeyValue{ Key:word, Value:"1" })
}
return res
}
func reduce(key string, values []string) string {
result := 0
for _, value := range values {
count, _ := strconv.Atoi(value)
result += count
}
return strconv.Itoa(result)
}
复制代码
上述例子中map函数输入键为文件名,输入值为文件内容,map函数将文件内容分割为多个单词,中间键值对为单词和单词出现次数“1”,而reduce函数将某个单词全部出现的次数相加。分布式
除了最简单的单词统计之外,还有不少的问题均可以套用MapReduce的模型解决。函数
<URL,1>
,reduce函数将URL的全部中间键值对的值相加,产生结果<URL,访问次数>
。<目标,来源>
。Reduce函数合并相同目标的中间值,产生<目标,list(来源)>
。<单词,文档编号>
的中间键值对,而后reduce函数合并中间键值对,产生结果<单词,list(文档编号)>
。最终结果组成一个反向索引,能够用于查询单词出现的文档。<键,记录>
,reduce函数则原样输出中间键值对便可。MapReduce须要处理的数据会被事先分割为M片断,中间数据被分配给R个片断,分割过程由分割函数hash(键) mod R
,分片数M和R以及哈希函数都由用户定义。学习
MapReduce处理结果一般会被保存到R个文件片断中,文件片断一般不须要被合并,直接用于其余的分布式任务。优化
Master会不断ping各个worker,若是某个worker产生错误,那么会被重置到可调度状态。发生错误的时候,已经完成的map任务须要被从新执行,由于map的结果保存到本地磁盘中,而已完成的reduce任务不须要被从新执行,由于reduce任务的结果被写入全局文件系统,ui
可让master按期将状态保存到磁盘,崩溃后直接利用保存的状态恢复。另外,也能够考虑直接在master奔溃的时候终止MapReduce任务。spa
在实现MapReduce实现中,由不少的技巧能够提升系统的运行效率。设计
<the,1>
这样经常使用词产生的中间数据传递给某个reduce任务的worker,这会给某个worker带来巨大的负担。解决的方法就是让map执行完成后调用合并函数处理一编中间数据。合并函数和reduce函数一般是同样的,只是调用场景不一样。