站在巨人的肩膀上才能看的更远
mapreduce
编程模型:
MapReduce编程模型的原理是:利用一个输入的key/value
这一键值对(pair)集合,来产生一个输出的key/value
键值对集合,在MapReduce中使用map
共和reduce
这两个函数来计算。
map
函数接收一个输入和key/value
键值对,然后产生一个中间的key/value
键值对值的集合。MapReduce库把所有的具有相同中间key
值的value
值集合在一起,然后传递给reduce
函数。
reduce
函数接受一个中间的key
值和一个相关的value
值的集合。reduce
函数合并这些value
值,形成一个较小的vlaue
值的集合。一般的,每次Reduce函数调用只产生0或1个输出value值。通常我们通过一个迭代器把中间value值提供给Reduce函数,这样我们就可以处理无法全部放入内存中的
大量的value值的集合。
类型(Types)
用户定义的Map
和Reduce
函数具有相关连的类型:
map (k1,v1) → list(k2,v2)
reduce (k2,list(v2)) → list(v2)
比如,输入的key和value值与输出的key和value值在类型上推导的域(domain)不同。此外,中间key和value值与输出key和value值在类型上推导的域相同。
实现(Implementation)
执行概括
通过将map
调用的输入数据自动分割成M个数据片段的集合,map
调用分不到多台机器上执行。输入的数据片段能够放到不同的机器上并行处理。使用分区函数将map
调用产生的中间的key值分成R各不同分区,reduce
函数调用也被分不到多台机器上执行。分区数量R和分区函数有用户来指定。
上图向我们展示了整个执行的过程,主要分为以下几个步骤:
- 用户程序首先调用MapReduce库将输入的文件分成M个数据片段,每个片段的大小一般是16MB-64MB。然后用户程序在机群中创建大量程序副本。
- 这些程序副本中有一个特殊的程序-
master
。副本中其他的程序都是worker
程序,由master
分配任务。由M个Map任务和R个Reduce任务将被分配,master
将一个Map任务或者Reduce任务分配给一个空闲的worker
。 - 被分配了map任务的worker程序读取相关的输入数据片段,从输入的数据片段中解析出
key/value
键值对,然后把这些键值对传递给用户自定义的map函数,由map函数输出中间的key/value
键值对,并缓存到内存中。 - 缓存中的键值对,通过分区函数分成R个区域,之后周期性的写入到本地磁盘。缓存的键值对在本地磁盘上的存储位置被回传到master,由master负责把这些存储位置存储到reduce worker。
- 当reduce worker 程序接收到master程序发来的数据存储位置后,使用RPC从map worker所在主机的磁盘上读取这些缓存数据。当reduce worker读取了所有的中间数据后,通过随key进行排序后是的具有相同的key值的数据聚合在一起。由于许多不同的key值映射到相同的reduce任务上,因此必须进行排序
- reduce worker 遍历 排序后的中间数据,对于每一个唯一的中间key值,reduce worker 程序将这个key值和他相关的中间的value值得集合传递给用户自定义的reduce哈桑农户,reduce函数的输出被追加到所属分区的输出文件。
- 当所有的map和reduce任务都完成后,master唤醒用户程序,在这个时候在用户程序里对mapreduce的调用才返回。
master数据结构
Master持有一些数据结构,它存储每一个map和reduce的任务状态,以及worker机器的标识。
master周期性的ping每一个worker。
技巧
- 分区函数
- 顺序保证
- Combiner函数
- 输入和输出类型
- 副作用
- 跳过损坏的记录
- 本地执行
- 状态信息
- 计数器
编程实现:
wait。。。。