MapReduce原理
- MapReduce是一个分布式运算程序的编程框架
- Mapreduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个hadoop集群上。
MAPREDUCE框架结构及核心运行机制
- 一个完整的MapReduce程序分布式运行时主要有三个部分组成:
- MapReduce的管理程序MRAPPMaster:负责整个程序的过程调度及状态协调。
- mapTask:负责map阶段的整个数据处理流程
- reduceTask:负责reduce阶段的整个数据处理流程
- MapReduce运行流程解析
- 当一个MapReduce程序启动时,最先启动的是MPAPPMaster:
- 他将根据job中的描述信息,计算出需要的maptask实例。
- 同时记录用户定义的partition信息分配reducetask。
- 在job中配置了所有MapReduce程序运行的参数,例如yarn集群的位置等参数
- 最后向集群申请机器启动相应数量的maptask进程。
- maptask进程启动之后,根据给定的数据切片范围进行数据处理,主体流程为:
- 利用客户指定的inputformat来获取RecordReader读取数据,形成输入KV对。
- 将输入KV对传递给客户定义的map()方法,做逻辑运算,并将map()方法输出的KV对收集到缓存。
- 将缓存中的KV对按照K分区排序后不断溢写到磁盘文件。
- MRAppMaster监控到所有maptask进程任务完成之后,会根据客户指定的参数启动相应数量的reducetask进程,并告知reducetask进程要处理的数据范围(数据分区)。
- Reducetask进程启动之后,根据MRAppMaster告知的待处理数据所在位置,从若干台maptask运行所在机器上获取到若干个maptask输出结果文件,并在本地进行重新归并排序,然后按照相同key的KV为一个组,调用客户定义的reduce()方法进行逻辑运算,并收集运算输出的结果KV,然后调用客户指定的outputformat将结果数据输出到外部存储。
- 当一个MapReduce程序启动时,最先启动的是MPAPPMaster:
MapTask并行度决定机制
问题:maptask的并行度决定map阶段的任务处理并发度,进而影响到整个job的处理速度,那么,mapTask并行实例是否越多越好呢?其并行度又是如何决定呢?
一个Job的map阶段并行度是由客户端在提交job时决定的。主要处理逻辑为:
将待处理数据执行逻辑切片(即按照一个特定切片大小,将待处理数据划分成逻辑上的多个split),然后每一个split分配一个mapTask并行实例处理。
而将文件逻辑切片主要由FileInputFormat的getSplit()方法实现。过程:
1. 获得文件目录下的所有文件列表
2. 遍历每一个文件,针对单个文件进行切片处理
3. 先获取当前处理文件大小。fs.sizeOf(…)
4. 计算切片大小(主要根据配置信息):
computeSplitSize(Math.max(miniSize, Math.max(miniSize, blockSize)))
//这里miniSize、miniSize均为用户指定,默认值为1和Long.MaxValue
//因此这里计算出来的切片大小为blockSize的大小,默认为128M。
5.文件大小 % 切片大小 < 1.1 : 就不分片了
文件大小 % 切片大小 > 1.1 : 执行分片,然后文件大小为分片后剩余大小。
这里1.1倍作用:例如切片大小为128M, 文件大小为130M ,就不会将文件分片,如果分片将分配两个mapTask,浪费计算资源。
ReduceTask并行度决定机制
reducetask的并行度同样影响整个job的执行并发度和执行效率,但与maptask的并发数由切片数决定不同,Reducetask数量的决定是可以直接手动设置:
//默认值是1,手动设置为4
job.setNumReduceTasks(4);
如果数据分布不均匀,就有可能在reduce阶段产生数据倾斜
注意: reducetask数量并不是任意设置,还要考虑业务逻辑需求,有些情况下,需要计算全局汇总结果,就只能有1个reducetask
尽量不要运行太多的reduce task。对大多数job来说,最好rduce的个数最多和集群中的reduce持平,或者比集群的 reduce slots小。这个对于小集群而言,尤其重要。