1、Map阶段:
a. 文件切片以后,每个切片对应一个MapTask算法
b. 在MapTask中,默认按行读取,每读取一行,就调用一次map方法数组
c. map方法在执行的时候会将结果(这个结果中已经包含了分区信息)写到MapTask自带的缓冲区中。注意:每个MapTask都会自带一个缓冲区
d. 当数据放到缓冲区中以后,数据在缓冲区中会进行分区(partition)、排序(sort)(扩展:在缓冲区中排序使用的排序算法是快速排序)。若是指定了合并类(combine),数据还会进行combine
e. 缓冲区是维系在内存中,默认是100M
f. 当缓冲区的使用达到指定条件(溢写阈值默认是0.8,即当缓冲区使用达到80%的时候会产生溢写)以后,MapTask会将这个缓冲区中的数据溢写(spill)到磁盘上产生溢写文件。后续的结果会继续写到缓冲区中。每一次溢写都会产生一个新的溢写文件
g. 若是产生了多个溢写文件,那么会将多个溢写文件合并(merge)成1个final out文件。若是溢写以后,后续结果放入缓冲区中可是没有达到溢写阈值,而数据又处理完成,那么MapTask会将溢写文件中的结果和缓冲区的结果直接合并(merge)到最后的final out文件中网络
h. 在merge过程当中,结果会再次进行分区和排序,因此final out文件是总体分好区而且排好序
i. 若是指定了合并类(Combiner),而且溢写文件的个数>=3个,那么在merge过程当中会自动进行一次combine
j. 注意问题:
i. 溢写不必定产生
ii. 溢写与否与输入的切片大小是没有直接关系
iii. 溢写文件的大小要考虑序列化因素
iv. 缓冲区本质上是一个字节数组,这个字节数组在底层作了改变,使缓冲区造成了一个环形的缓冲区。设置成环形的目的是为了减小寻址
v. 溢写阈值的做用是为了减小阻塞
2、Reduce阶段:
a. 每个ReduceTask都会启动fetch线程去MapTask中抓取当前要处理的分区的数据
b. ReduceTask会将抓取过来的数据暂时放到文件中存储,从每个MapTask中抓取的数据都会对应一个小文件
c. ReduceTask会将这些小文件去合并(merge)成一个文件,在merge过程当中,数据会进行排序 - 将局部有序变成总体有序 - merge过程当中的排序使用的排序算法是归并排序
d. merge完成以后,ReduceTask会将相同的键对应的值放到一块产生一个迭代器,这个过程从称之为分组(group)
e. 每个键调用一次reduce方法,reduce方法将结果写到HDFS上
f. 注意问题:
i. 默认fetch线程的数量为5
ii. fetch线程经过HTTP请求的方式去抓取数据
iii. merge因子默认为10,表示每10个小文件合成一个大文件
iv. ReduceTask阈值默认为0.05,即当有5%的MapTask执行结束,就启动ReduceTask开始抓取数据
3、Shuffle调优:
a. 调大缓冲区,实际生产环境中通常将这个值调为250~400M
b. 调大溢写阈值,能够减小和磁盘的交互可是同时增大了阻塞的几率
c. 实际生产环境中,尽可能增长Combine过程
d. 能够对final out文件进行压缩。这种方案是对网络资源的一种取舍。若是网络资源紧张能够考虑这种方式
e. 增多fetch线程的数量
f. 增大merge因子 - 不建议
g. 减少ReduceTask的阈值fetch
推荐使用的方法是acdespa