谈谈对MapTask任务分配和Shuffle的理解
一、切片与MapTask的关系
1、概述
大家要注意区分切片与切块的区别:
- 切块Block是HDFS物理上把数据分成一块一块的,默认是128M;
- 数据切片:只是在逻辑上对输入进行分片,并不会在磁盘上分成片进行存储;而是分成片对数据进行处理。
物理上HDFS会把数据进行切块存储,但是当进行数据处理时,取出来的一块数据是整体是比较大的,需要对数据进行切片处理。如果切片设置为100M,那么一个数据块128M会被分成两个切片。
而MapTask的任务数量既与切片的个数有关又与文件个数有关。
2、MapTask的决定因素
- 文件的大小:当切片为128M时,如果文件块的大于128M就会被分成2个split甚至多个。
- 文件的个数:FileinputFormat按照文件分割split,并且只会分割大文件,即那些大小超过HDFS块的大小的文件。如果HDFS中dfs.block.size设置为128,而输入的文件有100个,则划分后的split个数至少为100个。
- splitsize的大小:分片是按照splitsize的大小进行分割的,一个split的大小在没有设置的情况下,默认等于hdfs block的大小,但是程序可以通过两个参数进行设置,对splitsize进行调节。
InputSplit=Math.max(minSize, Math.min(maxSize, blockSize)
其中:
minSize=mapred.min.split.size
maxSize=mapred.max.split.size
我们可以在MapReduce程序的驱动部分添加如下代码:
TextInputFormat.setMinInputSplitSize(job,1024L); // 设置最小分片大小。
TextInputFormat.setMaxInputSplitSize(job,1024×1024×10L); // 设置最大分片大小。
3、总结
因此我们可以得出如下结论:MapTask的数量=小于split的文件个数+大于split的文件的个数/切片大小。
二、Shuffle的理解
1、概述
Shuffle:简单来说,就是将分布在集群中多个节点上的同一key的“键值对”信息,拉取到同一节点上;Shuffle过程中,各个节点上的相同key都会先写入到本地磁盘文件中,然后其他节点需要通过网络传输来去各个节点的磁盘拉取文件中相同key的值。而相同的key都被拉取到同一节点进行聚合操作时,还有可能因为内存不够,进而溢写到磁盘文件中。因此在Shuffle过程中,可能会发生大量的磁盘文件读取的IO操作,以及数据的网络传输操作。
2、通过一张图来解析一个Job的声明周期
如上图所以,一个job的声明周期如下所述:
- 首先对数据进行split,切成不同的分片
- 对不同的分片记性MapTask操作
- 进入Shuffle过程,对相同的key值拉取到同一节点的分区中;
- 进行Reduce聚合操作,将相同的key值进行统计;
- 将Reduce结果放入到一个结果文件中。