一、Mapreduce框架原理
一、InputFormat 数据输入
(1)MapTask并行度决定机制
数据切片是MapReduce程序计算输入数据的单位,一个切片会对应启动一个MapTask。一个Job的Map阶段的并行度由客户端在提交Job时候的切片数来决定的,每一个切片会分配一个MapTask并行实例处理,在默认情况下切片大小=BloclSize,切片时候不考虑数据集整体,针对每一个文件单独切片。
(2)FileInputFormat切片机制
首先会循环遍历输入数据的文件列表 按照单个文件切分,
1.如果输入目录下存在子目录,默认情况下不忽略,但是尽量不要让输入目录下存在子目录,如果不可控制,通过修改INPUT_DIR_NONRECURSIVE_IGNORE_SUBDIRS 参数对目录进行忽略处理。
2.判断当前文件是否可切分,主要针对压缩类型文件进行判断,如果遇到不可切分的压缩文件的话只能规划成一个切片
if (isSplitable(job, path)) {
// 获取当前处理文件的块大小
long blockSize = file.getBlockSize();3.计算切片大小 默认切片大小=块大小
// 如果想往大调整切片大小修改 minSize
// 如果想往小调整切片大小修改 maxSize
long splitSize = computeSplitSize(blockSize, minSize, maxSize);4.剩下的大小是否继续进行切分
采用循环来进行判断,但是要满足bytesRemaining)/splitSize > 1.1 // 目的:尽量为了避免小文件出现,让计算资源充分的利用
(3)InputFormat的类继承体系结构
IntPutFormat本身是一个抽象类
-- FileInputFormat是 IntPutFormat 的默认子实现类 其中实现getSplits() 切片功能
-- TextInputFormat 是 FileInputFormat 默认子实现 其中实现了 createRecordReader() 读取数据的功能
-- CombineFileInputFormat
-- CombineTextInputFormat 此类中也实现getSplits() 方法,主要针对小文件计算场景的。二、Shuffle的机制流程
当MapTask执行完map()方法后通过context对象写数据的时候开始执行shuffle过程。首先数据先从Map端写入到环形缓冲区内,写出的数据会根据分区规则进去到指定的分区,并且同时在内存中进行一个分区排序。环形缓冲区默认大小为100M,当数据写入的容量达到环形缓冲区的80%,数据开始向磁盘进行溢写,如果数据很多的情况下,会进行Nci溢写,这样在磁盘中就会产生多个溢写文件,并且保证每个溢写文件在区内是有序的,接下来在磁盘中会将多次溢写的文件归并到一个文件中,归并的过程会根据相同分区进行排序,保证归并完的文件是有序的,到此shuffle过程在Map端就完成了。
接着Map端输出的数据会作为Reduce端的输入数据再次进行汇总操作,此时ReduceTask会把每一个MapTask中计算完的相同分区的数据拷贝到reduce内存中,如果内存放不下,开始溢写磁盘,接着对数据进行归并排序。排序完后根据相同的key进行分组,将来同一组的数据会调用一次reduce方法。