MapReduce中map与reduce的个数

Map的个数

在map阶段读取数据前,FileInputFormat会将输入文件分割成split。split的个数决定了 map的个数。
影响map个数,即split个数的因素主要有:
  • HDFS块的大小,即HDFS中dfs.block.size的值。默认为128M
  • 文件的大小。
  • 文件的个数。FileInputFormat按照文件分割split,并且只会分割大文件,即那些大小超过HDFS块的大小的文件。
  • splitsize的大小。分片是按照splitszie的大小进行分割的,一个split的大小在没有设置的情况下,默认等hdfsblock的大小,但应用程序可以通过两个参数来对splitsize进行调节。

如默认一个block为128M,若一个文件为125M,则是一个map,若有三个125M的文件,就是三个map。如果一个文件为130M,则分为两个块,两个map。

可通过minimumsize和maximumsize两个参数设置:
splitsize=max(minimumsize,min(maximumsize,blocksize))
如果没有设置minimumsize和maximumsize,splitsize的大小默认等于blocksize


Reduce的个数

mapred.tasktracker.reduce.tasks.maximum可以决定个tasktracker并发执行的reduce数,建议为cpu核数
job.setNumReduceTasks(2);Job对象的这个方法可以用来设定总的reduce的数目

shuffle的过程,需要根据key的值决定将这条 (map的输出),送到哪一个reduce中去。送到哪一个reduce中去靠调用默认的org.apache.hadoop.mapred.lib.HashPartitioner的getPartition()方法来实现。

package org.apache.hadoop.mapred.lib;

import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.mapred.Partitioner;
import org.apache.hadoop.mapred.JobConf;

/** Partition keys by their {@link Object#hashCode()}. 
 */
@InterfaceAudience.Public
@InterfaceStability.Stable
public class HashPartitioner implements Partitioner {

  public void configure(JobConf job) {}

  /** Use {@link Object#hashCode()} to partition. */
  public int getPartition(K2 key, V2 value,
                          int numReduceTasks) {
    return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
  }
}
numReduceTasks默认值为1,所以默认一个reduce

可以自定义partitioner

    public static class myPartitioner extends Partitioner{

        @Override
        public int getPartition(Text key, LongWritable value, int numPartitions) {
            // TODO Auto-generated method stub
            final String string = key.toString();
            if("Calvin".equals(string) || "Harris".equals(string)) {
                return 0;
            }else {
                return 1;
            }
        }
        
    }

如上,如果key等于Calvin或者Harris两个字符串,就分到一个reduce中,否则另一个,所以启动了两个reduce


注意:

     job.setNumReduceTasks(int a)   b=自定义getPartition
  • a = 1,不管Partitioner返回不同值的个数b为多少,只启动1个reduce,这种情况下自定义的Partitioner类没有起到任何作用。
  • a>1且a>b,会启动a个reduce,但是只有b个reduce会得到数据,剩余的a-b个就会浪费
  • a>1且a
  • a=b时最理想的情况,合理利用资源,负载均衡




你可能感兴趣的:(Hadoop)