一、Shuffle中的两个优化:Combiner(组合器)&Compress(压缩)
首先给大家简单介绍一下MapReduce中shuffle机制:
●MapReduce中,map阶段处理的数据如何传递给reduce阶段,是MapReduce框架中最关键的一个流程,这个流程就叫shuffle;
●shuffle: 洗牌、发牌——(核心机制:数据分区,排序,缓存,合并)
●具体来说:就是将MapTask输出的处理结果数据,分发给ReduceTask,并在分发的过程中,对数据按key进行了分区和排序等处理;
1、Combiner
本质:提前进行聚合,让MapTask分担ReduceTask的工作
(针对WordCount快速了解)
不使用Combiner组合器:
这时就非常不合理,因为MapTask是有多个的,个数一般远大于ReduceTask 的个数。
解决:Combiner:发生在Map端shuffle中的Reduce的过程,提前在Map进行Reduce的聚合
本质:在Map端先做了一次Reduce的工作,分担的Reduce的任务
设计:利用MapTask有多个,每个Maptask处理数据也比较少,每个MapTask先聚合一次,聚合以后的结果再给Reduce
Combiner:就是在Map端的聚合 ,做的工作与Reduce实现的聚合是一模一样的一般称为Map端的Reduce
在MapTask中重写reduce()方法:触发条件:
- 每次Spill溢写时会被调用
- 合并时文件书超过三个会被调用
可以在环形缓存区溢写文件时调用combiner函数,也可以在溢写的小文件合并成大文件时调用combiner。但要保证不管调用几次combiner函数都不会影响最终的结果,所以不是所有处理逻辑都可以使用combiner组件,有些逻辑如果在使用了Combiner函数后会改变最后Reduce的输出结果。
Combiner只应该用于那种Reduce的输入key/value与输出key/value类型完全一致,且不影响最终结果的场景。比如累加,最大值等。
2、Compress
压缩的本质:通过算法将数据重新进行存储,节省更多的空间,牺牲了CPU的资源(时间换空间)
作用:减少存储系统读写字节数、提高网络带宽和磁盘空间效率。
基本原则:
计算(CPU)密集型作业,少用压缩;
IO密集型作业,多用压缩
能压缩数据的位置:
MapTask写出(常用):MapTask写出的数据不需考虑是否可切分这个选项,只需要从性能角度考虑,推荐Snappy
ReduceTask写出:
ReduceTask写出的数据需要考虑是否是下一个作业的入口数据:
如果是,不推荐使用不可切分压缩算法;
如果计算后的结果无需再次计算,就是归档存储,且后续再计算的可能性也比较小,使用高比例压缩算法,节省存储空间
二、合并(Merge)
MapTask中:
因为溢写会产生很多有序(分区 key)的小文件,而且小文件的数目不确定
后面向Reduce传递数据带来很大的问题
所以将小文件合并成一个大文件,将来拉取的数据直接从大文件拉取即可
合并小文件的时候同样进行排序(归并排序),最终产生一个有序的大文件
每次最多合并十个文件
最终合并为file.out和file.out.index
Merge 是为了让传输的文件数量变少,但是网络传输数据量并没有改变,只是减少了网络 IO 次数。
ReduceTask中:
合并(Merge):同上
聚合(Reduce):
将文件中的数据读取到内存中
一次性将相同的key全部读取到内存中
直接将相同的key得到结果-->最终结果