MapReduce归纳总结
一、Mapper端的shuffle过程
- 在MapReduce程序刚开始的时候会先对文件进行切片。如果文件不可切,则将整个文件作为一个切片进行处理。如果文件可切,则进行切分,但是需要注意的是如果剩余数据量/splitsize<=1.1,则剩余的数据整体作为一个分区来进行处理
- 每一个分区会分配给一个MapTask来处理。MapTask在接收到FileSplit之后进行按行读取,每读取一行调用一次map方法
- 每执行完一次map方法之后会将计算结果写到缓冲区中。缓冲区是维系在内存中的
- 缓冲区的大小默认是100M,可以通过io.sort.mb来进行调节
- 在缓冲区中,会对数据进行分区-partition,排序 - sort。如果指定了合并 (combine)操作,则在缓冲区中也会进行combine操作
- 当缓冲区的容量利用率达到阈值0.8的时候,会启动给一个后台线程将缓冲区中的数据写到指定目录下的溢写文件中,这个过程称之为是溢写 (Spill),而每次的Spill都会产生一个新的溢写文件
- 等最后所有的数据都写完之后,会将所有的溢写文件进行一次合并 (merge),合并到一个新的分区并且排序的文件中。需要注意的是merge过程并不减少数据量,而combine过程会减少数据总量
- 如果在最终合并的时候,溢写文件个数>=3,那么合并完成之后会再执行一次Combiner
二、Reducer端的shuffle过程
- ReduceTask通过Http的方式来得到输出文件的分区,这个过程称之为fetch
- 每一个ReduceTask将获取的分区的数据再次进行merge,然后进行排序
- 将相同的key做聚合,将值放入迭代器中,这一步称之为分组
- 调用reduce方法,将key和迭代器传入
三、流程图
MapReduce的shuffle·过程
四、注意问题
- 当产生溢写的时候,缓冲区最后残留的数据会flush到最后一个溢写文件中
- 在默认情况下,环形缓冲区的大小为100M,溢写阈值为0.8
- 不能凭借一个MapTask处理的切片大小来衡量MapTask之后的输出数据的多少
- 每一个切片对应一个MapTask,每一个MapTask对应一个缓冲区
- 不同的文件不会进行合并,所以不能直接以输入文件的总大小和计算Maptask的个数。
- 缓冲区又叫环形缓冲区,好处在于可以重复利用同一块地址的缓冲区
- 阈值的作用是避免Spill中过程数据丢失
- fetch的默认线程数是5
- ReduceTask的启动阈值为5%,即当5%的MapTask完成之后,ReduceTask就开始启动
五、优化措施
MR的调优过程可分为二个方面考虑:map端的调优和reduce端的调优
Map调优:
a. 调大缓冲区,减小溢写的频率。
b. 可以引入combine过程,减小网络传输的数据量
c.引入压缩机制,减小网络传输的数据量
Reduc优:
a.增多fetch线程的数量
b.降低ReduceTask的启动阈值
c.适当提高merge因子,比如设为10,即便是每10个文件合并成一个文件