· MapReduce是怎样为数据进行分组,整合等操作的呢?这就涉及到Map和Reduce在中间十分关键的衔接部分Shuffle。
上面介绍了Map 和 Reduce的各自的任务和总的流程,MapReduce是怎样为数据进行分组,整合等操作的呢?这就涉及到Map和Reduce在中间十分关键的衔接部分Shuffle。
什么是shuffle?shuffle原意是洗牌,混乱。而在MapReduce中shuffle却是将一些凌乱的数据规整成有一定规则的过程。Shuffle是横跨MapReduce的两端。
下面详细介绍一下shuffle的运行过程:
在Mapper中的shuffle
1.当MapTask获取到Split之后按行读取数据
2.每读取一行调用一次map方法
3.每一行经过map方法处理以后,会产生一个或者多个key-value结果
4.Key-value的数据会暂时存到一个环形的缓冲区,这个缓冲区维系在内存中。
5.在缓冲区中会对数据进行分区-partition, 排序-sort, 合并-combine操作
6.当缓冲区使用在达到阈值(已使用缓冲区/缓冲区的总量,默认是0.8),将缓冲区的数据写到当前的磁盘中(spill—溢写),保存数据的格式—溢写。
7.对于单个溢写文件而言,里面的数据是分好区排好序的,但是对于整体所有的溢写文件而言是无序的。
8.等到所有的数据写完,会将所有的溢写文件进行一次合并(merge),合并到一个新的分区并且排序的文件中
9.再最终合并的时候,溢写文件个数<=3,那么合并完成之后会再执行一次Combinaer
在这个过程中需要注意的问题:
1. 当产生溢写的时候,缓冲区最后残留的数据会flush到最后一个溢写文件中
2.Spill理论上默认是80M,但是要考虑序列化以及最后的冲刷等因素
3.不能凭借一个MapTask处理的切片大小来衡量MapTask之后的输出数据的多少
4.每一个切片对应一个MapTask,每一个MapTask对应一个缓冲区
5.缓冲区本质上是一个字节数组
6.缓冲区又叫环形缓冲区,好处在于可以重复利用同一块地址的缓冲区
7.阈值的作用是避免Spill过程产生阻塞
8.merge过程可能不会发生
Reduce中的shuffle:
1.ReduceTask启动多个后台线程发起HTTP请求抓取数据----fetch
2.当前的ReduceTask值抓取对应分区的数据
3.RedcueTask从不同的MapTask上抓取了大量的数据,然后对这些数据进行merge(因为每个MapTask中合并的文件中有各个分区的数据)
4.在merge过程中,会对数据进行一次排序,保证当前分区中的数据有效(在这之后会进行一次分组过程)
5.Merge之后数据要进行一次分组(group),将相同的键所对应的值放到一个ArrayList
6.将ArrayList传递到Reducer中,Reducer将ArrayList转化为一个迭代器传到Reduce方法中
在Reduce中需要注意:
1.fetch的线程数量默认为5个
2.ReduceTask在启动的时候有一个阈值,这个阈值时表示有几个MapTask
3.执行完成之后就要启动ReduceTask,阈值默认时0.05(当有5%的mapTask执行完成之后,启动ReduceTack)
4.merge因子是10(默认十个合一个);
那么Shuffle调优就很重要的,主要有以下的方式:
Reduce阶段:
1.增加fetch线程的数量
2.减小reduceTask的阈值—尽量不要动
3.调大merge因子
Mapper阶段:
1.调大缓冲区。建议在250—400M
2.指定combiner减少数据量
3.压缩数据以减少网络传输过程中的时间消耗(这种方式实际上是在网络和内存之间进行了取舍)