默认TextInputFormat 》 fileinputformat》inputformat map partitioner compare reduce outputformat
mr 之间总称为shuffle````
RecordReader 是 inputformat中的成员变量 中有方法read() 返回一个kv对
自定义mapper之后 到outputCollector然后环形缓冲区默认到内存100M 默认阀值80M溢出,留出点内存排序 先hashPartitoner key模值取余reduce个数 所以相同的key就会到同一个分区 分区再每个分区排序compare默认按首字母排序,强调先分区后排序,即map结果知道自己将来要往哪个reduce去所以溢出的每一小段都是分区且有序,分区且有序 默认按hashpartitioner 可以理解为相同的key到相同的reduce,分区后会有很多次排序 merge reduce端的合并等
数组索引指针,溢出前会有个combiner结合如a1 a 1 a1 a1 a1 c1 c1 c1 c1 c1 键值对通过combiner就会变成a5 c5 写到文件分区且区内有序,溢出写到多个文件,
然后merge 合并也会调用combiner本地 combiner其实和reduce差不多 大大减少了网络io传送上一步溢出的多个文件。再进行一次归并排序成为一个大的分区且区内有序的文件,
接着 reduce去map机器上去拿通过网络调用,怎么知道map进行完了?
reduce拿对应分区的文件到本地磁盘,再合并归并排序拿来的对应分区的文件组成一个大文件,无分区有序的文件
reduce再通过GroupingComparaor(k,nextk)进行判断K是否相同,相同一组K相同的调用一次自定义的reduce,所以可以通过重写其来实现自定义的一组数据处理,如自定义的bean每个bean是一个不同的对象,则可通过重写让其认为是同一个对象
reduce 处理同k然后迭代Value输出 通过outputformat 默认TextOutputFormat RecordWriter write(k,v)一组为一行
客户端通过inputformat的getsplit获得切片规划 读文件通过RecordReader
关于大量小文件的优化策略
默认情况下 textInputFormat对任务的切片规划是按大小来分,如果很小小于128M,那么每个小文件
都会有一个maptask任务来处理,大量小文件就会有大量的maptask,效率低下,且会占用namenode元数据空间
所以
预处理将小文件合成大文件再上传至hdfs
若小文件已经上传至hdfs可以使用combineFileinputFormat
job.setinputformat(combinefileinputformat) 默认fileinputformat
combineTextInputFormat.setMaxInputSplitSize(job,)
set Min
TextInputFormat RecordReader read
mapper() map(k,v) context.write OutPutCollector环形缓冲区排序 内存 默认100M 默认写到80溢出
溢出前分区(k.hashCode % numReuce)排序快排
spiller溢出到磁盘文件(溢出的时候可以进行combiner合并) 多个spiller文件(分区且有序)会进行合并称之为merge(merger时也可以进行combiner合并) merge中是归并排序(分区且有序)
分区数量和reduce数量相对应,
reduce通过网络通信去相应的分区去拿数据,拿到多个小文件,再进行归并排序
对相同key的数据进行处理也可以重写groupingComparator判断那些为一组
相同key的value被放到一个迭代器里面
context.write(k,v) TextOutPutFormat recordwrite write(k,v)
combiner 合并类似与reduce减少小文件的数量,提高效率,因为网络传输,但是combiner只能用在求和之类的场景中,即combiner对最后的结果不能产生影响