1、MapTask
并行度:就是分布式集群运行了多少个任务
MapTask任务:说白了就是分而治之中的分了多少个小任务,类似于代码中map函数的调用次数,对原始数据进行任务划分,让不同的数据跑在不同的节点上。
MapTask的任务划分究竟与什么有关联?
在FileInputFormat类中有一个getSplits()方法,这个方法就是决定每个MapTask的任务划分
split概念;逻辑切片,只是进行一个逻辑划分并没有将真正的数据进行切分
一个MapTask最终对应到数据上就是对应一个切片:1个split--->1个MapTask--->1个Yarn
主要代码如下:
public List<InputSplit> getSplits(JobContext job) throws IOException {
Stopwatch sw = (new Stopwatch()).start();
long minSize = Math.max(this.getFormatMinSplitSize(), getMinSplitSize(job));
long maxSize = getMaxSplitSize(job);
List<InputSplit> splits = new ArrayList();
List<FileStatus> files = this.listStatus(job);
Iterator i$ = files.iterator();
这里逻辑切片大小应该是多少?
假设:切片大小为1G,那么在当我们计算任务数据的时候,将会从多个节点进行拉取
假设:切片大小为100M,会造成第一个计算任务取得的是第一个块0-100M之间的数据,第二个计算任务取得是101-200M,同样会造成跨数据块的读取,产生网络传输,性能比较慢
所以将切片大小设置为128M最合适
面试题:切片和块的关系?
没有实际的切分,一个是逻辑上的切分,一个是数据存储的物理划分,默认情况下切片大小和块大小一致。
2、ReduceTask
当数据量特别大的时候,如果计算只有一个reduce任务,只在一个节点上跑,其他节点没事干,导致集群性能不高,并且执行任务的节点压力过大
ReudceTask任务的并行度怎么设置?
job.setNumReduceTasks(3); 设置ReduceTask的个数,参数传入的代表最终启动的ReduceTask数量,生成的3个文件各自统计不同的key结果,最终3个文件合并在一起就是最终的统计结果,内部是MapReduce的默认分区(HashPartitioner)决定的,不同map输出的key进入到不同的reducetask中。
分区的作用仅仅是规划每个reducetask应该计算的数据范围
默认情况下:key.hashCode() & Integer.MAX_VALUE)% numReduceTasks
ReduceTask的并行度最终会影响到程序的总体执行效率,设计分区的时候一定要足够了解数据,如果设计不好,容易产生数据倾斜。