3 MapReduce

Wu Jun 2019-04-24 22:06:48
11 分布式 > 02 分布式计算

MapReduce建立在HDFS基础上,为海量的数据提供了一个计算框架。由两个阶段组成:Map和Reduce,用户只需实现map()和reduce()两个函数,即可实现分布式计算。

1 架构

主从结构

1)JobTracker(主节点)

只有一个

2)TaskTracker(从节点)

有很多个

2 运行流程

Map阶段的输入来自HDFS中的文件,一个map任务处理一个文件块。Map任务的输出会作为Reduce的输入,Reduce是对数据集进行精简,然后得出相应结果。

MapReduce的执行过程一般过程分为:Split, Map, Shuffle, Reduce, Output几个阶段

示例

hello java
hello c
hello php
hello javascript
hello java language
hello c language
hello php language
hello javascript language
1 Split阶段

文件分块。得益于HDFS的特性,文件在HDFS中是分块存储的。假设每个文件块包括2行内容的话,一共四个文件块:

文件块 内容
0 hello java
hello c
1 hello php
hello javascript
2 hello java language
hello c language
3 hello php language
hello javascript language
2 Map阶段

每个块由一个map任务来处理,map函数将各个文件块的内容转换成新的key-value对

文件块 内容 Map任务 map函数输出
0 hello java
hello c
Map任务0 [hello:1]
[java:1]
[hello:1]
[c:1]
1 hello php
hello javascript
Map任务1 [hello:1]
[php:1]
[hello:1]
[javascript:1]
2 hello java language
hello c language
Map任务2 [hello:1]
[java:1]
[language:1]
[hello:1]
[c:1]
[language:1]
3 hello php language
hello javascript language
Map任务3 [hello:1]
[php:1]
[language:1]
[hello:1]
[javascript:1]
[language:1]
3 Shuffle阶段

每个Mapper任务

最后发送给Reducer任务

Map任务 map函数输出 分区 排序 分组 Combiner
Map任务0 [hello:1]
[java:1]
[hello:1]
[c:1]
分区0
[hello:1],[java:1],[hello:1]
分区1
[c:1]
分区0
[hello:1],[hello:1],[java:1]
分区1
[c:1]
分区0
[hello:{1,1}],[java:1]
分区1
[c:1]
分区0
[hello:2],[java:1]
分区1
[c:1]
Map任务1 [hello:1]
[php:1]
[hello:1]
[javascript:1]
分区0
[hello:1],[php:1],[hello:1]
分区1
[javascript:1]
分区0
[hello:1],[hello:1],[php:1]
分区1
[javascript:1]
分区0
[hello:{1,1}],[php:1]
分区1
[javascript:1]
分区0
[hello:2],[php:1]
分区1
[javascript:1]
Map任务2 [hello:1]
[java:1]
[language:1]
[hello:1]
[c:1]
[language:1]
分区0
[hello:1],[java:1],[hello:1]
分区1
[language:1],[c:1],[language:1]
分区0
[hello:1],[hello:1],[java:1]
分区1
[c:1],[language:1],[language:1]
分区0
[hello:{1,1}],[java:1]
分区1
[c:1],[language:{1,1}]
分区0
[hello:2],[java:1]
分区1
[c:1],[language:2]
Map任务3 [hello:1]
[php:1]
[language:1]
[hello:1]
[javascript:1]
[language:1]
分区0
[hello:1],[php:1],[hello:1]
分区1
[language:1],[javascript:1],[language:1]
分区0
[hello:1],[hello:1],[php:1]
分区1
[javascript:1],[language:1],[language:1]
分区0
[hello:{1,1}],[php:1]
分区1
[javascript:1],[language:{1,1}]
分区0
[hello:2],[php:1]
分区1
[javascript:1],[language:2]
4 Reduce阶段

Shuffle结束后,同一分区的数据会传送给同一个Reducer任务。

Reducer任务接收到key-value对后会先根据key进行排序和分组,最后执行Reducer函数输出结果。

Reduce任务 输入 排序 分组 输出
Reduce任务0 [hello:2]
[java:1]
[hello:2]
[php:1]
[hello:2]
[java:1]
[hello:2]
[php:1]
[hello:2]
[hello:2]
[hello:2]
[hello:2]
[java:1]
[java:1]
[php:1]
[php:1]
[hello:{2,2,2,2}]
[java:{1,1}]
[php:{1,1}]
[hello:8]
[java:2]
[php:2]
Reduce任务1 [c:1]
[javascript:1]
[c:1]
[language:2]
[javascript:1]
[language:2]
[c:1]
[c:1]
[javascript:1]
[javascript:1]
[language:2]
[language:2]
[c:{1,1}]
[javascript:{1,1}]
[language:{2,2}]
[c:2]
[javascript:2]
[language:4]
Output阶段

输出格式会转换最终的键值对并写入文件。默认情况下键和值以tab分割,各记录以换行符分割。因此可以自定义更多输出格式,最终数据会写入HDFS。类似记录读取,自定义输出格式不在本书范围。