天天看点

快速理解MapReduce

  map本意可以理解为地图,映射(面向对象语言都有map集合),这里我们可以理解为从现实世界获得或产生映射。reduce本意是减少的意思,这里我们可以理解为归并前面map产生的映射。

  按照google的mapreduce论文所说的,mapreduce的编程模型的原理是:利用一个输入key/value对集合来产生一个输出的key/value对集合。mapreduce库的用户用两个函数表达这个计算:map和reduce。用户自定义的map函数接受一个输入的key/value对值,然后产生一个中间key/value对值的集合。mapreduce库把所有具有相同中间key值的中间value值集合在一起后传递给reduce函数。用户自定义的reduce函数接受一个中间key的值和相关的一个value值的集合。reduce函数合并这些value值,形成一个较小的value值的集合。

  通过将map调用的输入数据自动分割为m个数据片段的集合,map调用被分布到多台机器上执行。输入的数据片段能够在不同的机器上并行处理。使用分区函数将map调用产生的中间key值分成r个不同分区(例如,hash(key) mod r),reduce调用也被分布到多台机器上执行。分区数量(r)和分区函数由用户来指定。

  mapreduce实现的大概过程如下:

  1.用户程序首先调用的mapreduce库将输入文件分成m个数据片度,每个数据片段的大小一般从16mb到64mb(可以通过可选的参数来控制每个数据片段的大小)。然后用户程序在集群中创建大量的程序副本。

  2.这些程序副本中的有一个特殊的程序master。副本中其它的程序都是worker程序,由master分配任务。有m个map任务和r个reduce任务将被分配,master将一个map任务或reduce任务分配给一个空闲的worker。 

  3.被分配了map任务的worker程序读取相关的输入数据片段,从输入的数据片段中解析出key/value对,然后把key/value对传递给用户自定义的map函数,由map函数生成并输出的中间key/value对,并缓存在内存中。 

  4.缓存中的key/value对通过分区函数分成r个区域,之后周期性的写入到本地磁盘上,会产生r个临时文件。缓存的key/value对在本地磁盘上的存储位置将被回传给master,由master负责把这些存储位置再传送给reduce worker。 

  5.当reduce worker程序接收到master程序发来的数据存储位置信息后,使用rpc从map worker所在主机的磁盘上读取这些缓存数据。当reduce worker读取了所有的中间数据(这个时候所有的map任务都执行完了)后,通过对key进行排序后使得具有相同key值的数据聚合在一起。由于许多不同的key值会映射到相同的reduce任务上,因此必须进行排序。如果中间数据太大无法在内存中完成排序,那么就要在外部进行排序。 

  6.reduce worker程序遍历排序后的中间数据,对于每一个唯一的中间key值,reduce worker程序将这个key值和它相关的中间value值的集合(这个集合是由reduce worker产生的,它存放的是同一个key对应的value值)传递给用户自定义的reduce函数。reduce函数的输出被追加到所属分区的输出文件。 

  上面过程中的排序很容易理解,关键是分区,这一步最终决定该键值对未来会交给哪个reduce任务,如统计单词出现的次数可以用前面说的hash(key) mod r来分区,如果是对数据进行排序则应该根据key的分布进行分区。

快速理解MapReduce

图1 mapreduce过程

  假设我们需要处理一批有关天气的数据,其格式如下: 按照ascii码存储,每行一条记录,每一行字符从0开始计数,第15个到第18个字符为年,第25个到第29个字符为温度,其中第25位是符号+/-,现在需要统计出每年的最高温度。

  0067011990999991950051507+0000+ 

  0043011990999991950051512+0022+ 

  0043011990999991950051518-0011+ 

  0043012650999991949032412+0111+ 

  0043012650999991949032418+0078+ 

  0067011990999991937051507+0001+ 

  0043011990999991937051512-0002+ 

  0043011990999991945051518+0001+ 

  0043012650999991945032412+0002+ 

  0043012650999991945032418+0078+ 

  mapreduce主要包括两个步骤:map和reduce 每一步都有key/value对作为输入和输出: 

  map阶段的key/value对的格式是由输入的格式所决定的,如果是默认的textinputformat,则每行作为一个记录进程处理,其中key为此行的开头相对于文件的起始位置,value就是此行的字符文本,map阶段的输出的key/value对的格式必须同reduce阶段的输入key/value对的格式相对应

  对于上面的例子,在map过程,输入的key-value对如下: 

  (0 ,0067011990999991950051507+0000+) 

  (1 ,0043011990999991950051512+0022+) 

  (2 ,0043011990999991950051518-0011+) 

  (3 ,0043012650999991949032412+0111+) 

  (4 ,0043012650999991949032418+0078+) 

  (5 ,0067011990999991937051507+0001+) 

  (6 ,0043011990999991937051512-0002+) 

  (7 ,0043011990999991945051518+0001+) 

  (8 ,0043012650999991945032412+0002+) 

  (9 ,0043012650999991945032418+0078+) 

  将上面的数据作为用户编写的map函数的输入,通过对每一行字符串的解析,得到年/温度的key/value对作为输出: 

  (1950, 0) 

  (1950, 22) 

  (1950, -11) 

  (1949, 111) 

  (1949, 78) 

  (1937, 1) 

  (1937, -2) 

  (1945, 1) 

  (1945, 2) 

  (1945, 78) 

  在reduce过程,将map过程中的输出,按照相同的key将value放到同一个列表中作为用户写的reduce函数的输入 

  (1950, [0, 22, –11]) 

  (1949, [111, 78]) 

  (1937, [1, -2]) 

  (1945, [1, 2, 78]) 

  在reduce过程中,在列表中选择出最大的温度,将年/最大温度的key/value作为输出: 

  其逻辑过程可用如下图表示: 

快速理解MapReduce

 参考:

<a target="_blank" href="http://desert3.iteye.com/blog/865243">http://desert3.iteye.com/blog/865243</a>

<a target="_blank" href="http://www.cnblogs.com/duguguiyu/archive/2009/02/28/1400278.html">http://www.cnblogs.com/duguguiyu/archive/2009/02/28/1400278.html</a>

<a target="_blank" href="http://www.cnblogs.com/mitiskysean/p/3320451.html">http://www.cnblogs.com/mitiskysean/p/3320451.html</a>