Partition和ReduceTask的关系
先看源码:
numPartitions = conf.getNumReduceTasks(); if (numPartitions > 1) { //设置了ReduceTask个数后(大于1),默认通过下面的getPartition()对数据进行分区 partitioner = (Partitioner<K,V>) ReflectionUtils.newInstance(conf.getPartitionerClass(), conf); } else { partitioner = new Partitioner<K,V>() { @Override public void configure(JobConf job) { } @Override public int getPartition(K key, V value, int numPartitions) { return numPartitions - 1; //默认情况下,ReduceTask个数为1,此时只有一个分区 即partition 0 } //默认分区是根据key的hashcode对ReduceTasks个数取余得到的,用户无法控制哪个key存储到哪个分区
public int getPartition(K key, V value, int numReduceTasks) { return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks; }
结论:
1.ReduceTask的数量由job提交时的参数决定:job.setNumReduceTasks()。设置为多少,就开启多少个ReduceTask,默认为1。设置为0时,则表示没有Reduce阶段,只有Map阶段。生成文件数量由ReduceTask数量决定。
2.Partitioner的数量由ReduceTask的数量决定,Partitioner数量 =ReduceTask数量。
其中: 1)若ReduceTask = 1 ,无论用户有没有自定义分区规则,都只有一个分区。
2)若设置ReduceTask >1,则 如果用户没有自定义Partitioner,则按照默认的HashPartitioner对数据进行划分。
如果用户自定义了Partitioner,则其中的分区的个数不能超过Partittion的数量,否则会 Exception。