本文主要了解Hadoop重要组成部分之一的分布式计算框架MapReduce。了解其架构原理以及任务处理过程。
一、MapReduce概述
MapReduce简介
MapReduce 是一个并行的软件框架,用户可以基于该框架开发用于海量数据计算的应用程序。这些应用程序可以运行在大规模集群上,并具有可靠和容错能力。它能够将负责的任务分解为若干个简单的任务处理,如下图(注:图片来源于网络)。
![](https://i-blog.csdnimg.cn/blog_migrate/1f2097e888506d45c40a14bab21a1048.png)
MapReduce特点
将复杂的、运行与大规模集群上的并行计算过程抽象到2个函数,map 和 reduce。
编程容易,不需要掌握分布式并行计算细节。
将存储在分布式文件系统中的海量数据集切分为多个独立的分片,被多个Map任务并行处理。
计算向数据靠拢,减少移动数据带来的网络开销。
采用Master/Slave架构
二、MapReduce工作流程
按照上图可以把MapReduce过程分为以下几个步骤:
输入数据:对文本进行分片,将每个分片的数据作为一个MapTask输入。
Map阶段:MapTask处理数据输入,最终输出给ReduceTask。MapTask 在输出数据时,为每条数据定义一个key,这个key值决定这条数据最终会被发送给哪个ReduceTask,具有相同key的数据会被发送给同一个ReduceTask。
Shuffle阶段-合并排序:进入Reduce阶段前,MapReduce框架会对数据按照Key值排序(快排)。如果指定了合并(Combiner),会对中间过程的输出具有相同key的数据进行本地聚集。
Shuffle阶段-分配Reduce:通过对key的hash计算并对ReduceTask个数取模,计算出分区ID。一个分区可以包含多个key, 同一个Key只能存在一个分区。一个分区对应一个Reduce;
Reduce阶段:ReduceTask 会将key相同的数据进行Reduce操作,最后将结果保存在存储上。
三、MapReduce核心概念补充
切片大小确定
默认情况下,切片的大小和存储在HDFS的块大小一致128M,可以通过maxSize 和 minSize 调节。
切片的信息会被写到一个切片规划文件中用于后续的YARN计算开启MapTask的数量。
Map数量确定
map数 = Split数 = FileInputFormat.getSplits()
合适的Map数据会减小任务调度的负担。
Shuffle机制
从上图可以看到,Shuffle 处于map 之后reduce之前的过程。
a. MapTask 收集的map()方法输出的KV对会被放入一个默认100M的缓冲区中。
b. 达到缓存区的溢出阈值(默认80%)就会在本地落盘。多个溢出文件会被合并成大的溢出文件。
c. 在溢出和合并的过程中会进行分区和key的排序。
d. ReduceTask会根据自己的分区号,去各个MapTask机器上获取相应的分区数据。
e. ReduceTask将来自同一个分区不同MapTask的结果文件进行合并排序。
f. 合并成大文件后shuffle 结束,进入Reduce过程。
Reduce数量确定
Shuffle机制中提到一个概念:分区。
可理解为输出的文件个数,默认使用key的hash值对ReduceTask个数取模,如果不设置ReduceTask的个数,不管有多少个MapTask,数据最终会到一个0号分区(分区号必须从0开始,逐渐递加),即只有一个reduce处理,最终输出到一个文件中,这样MR的瓶颈就会在reduce阶段。
为解决上述问题,需要自定义分区以及设置ReduceTask个数。
如果 ReduceTask 数 > getPartition()的结果,会产生多个空的输出文件。
如果 ReduceTask 数 < getPartition()的结果,会有一部分数据无处放置。
如果 ReduceTask 数=1,则只会产生一个输出文件。
4.1 自定义分区设置(重写getPartition()方法):
//指定自定义分区器
job.setPartitionerClass(CustomPartitioner.class);
//指定ReduceTask个数
job.setNumReduceTasks(5);
4.2 ReduceTask数的确定
ReduceTask的数据量没有固定的,可根据业务实际需求、参与运行计算的节点数等方式开衡量设定。数量太少可能出现部分计算节点负载过高,数量太大会影响shuffle过程,最终输出过多的小文件。
四、参考