一、切片
一个job的map阶段并行度由客户端在提交Job是决定,而客户端对map阶段并行度的规划的基本逻辑为:将待处理数据执行逻辑切片(即按照一个特定切片大小,将待处理数据划分成逻辑上的多个split),然后每一个split分配一个mapTask并行实例处理;这段逻辑及形成的切片规划描述文件,由FileInputFormat实现类的getSplits()方法完成。
切片大小的确认函数方法
protected long computeSplitSize(long blockSize, long minSize,
long maxSize) {
return Math.max(minSize, Math.min(maxSize, blockSize));
}
其中
blockSize = file.getBlockSize()
minSize = Math.max(getFormatMinSplitSize(),getMinSplitSize(Job))
#getFormatMinSplitSize()返回值1
#getMinSplitSize(Job)返回值为SPLIT_MINSIZE = mapreduce.input.fileinputformat.split.minsize
maxSize = getMaxSplitSize(job)
#getMaxSplitSize(job)返回值为SPLIT_MAXSIZE = mapreduce.input.fileinputformat.split.maxsize
结论:
切片大小取minSize,maxSize,blockSize三者的中间值,默认情况blockSize为中间值
当需要增加切片大小,增加minSize值
当需要减小切片大小,减小maxSize值.
修改的具体方法:
FileInputFormat.setMaxInputSplitSize(job, size);
FileInputFormat.setMinInputSplitSize(job, size);
注意一般情况下不会修改切片的大小
二、reducetask并行度
reducetask的并行度同样影响整个job的执行并发度和执行效率,但与maptask的并发数由切片数决定不同,Reducetask数量的决定是可以直接手动设置:
job.setNumReduceTasks(4);
三、分区
在将map()函数处理后得到的(key,value)对写入到缓冲区之前,需要先进行分区操作,这样就能把map任务处理的结果发送给指定的reducer去执行,从而达到负载均衡,避免数据倾斜。MapReduce提供默认的分区类(HashPartitioner,其抽象Partitioner),其核心代码如下:
public class HashPartitioner<K, V> extends Partitioner<K, V> {
/*
key:map端输出的key
value:map端输出的value
numReduceTasks:reducetask的个数
*/
public int getPartition(K key, V value,
int numReduceTasks) {
return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
}
}
也可自定义分区类MyPartition,可使用job.setPartitionerClass(MyPartition.class)调用
四、MRJOB修改任务个数
hadoop任务调度优先级:
--jobconf mapreduce.job.priority=VERY_HIGH
map reduce 个数限制 :
--jobconf mapred.map.tasks=20
--jobconf mapred.reduce.tasks=5