MapReduce中的Map,Reduce个数设定

一、Map的个数

    在map阶段读取数据前,FileInputFormat会将输入文件分割成spilt,而spilt的个数决定了map的个数(一个spilt分片对应一个map)。影响map个数的因素只要有:

    1)文件的大小。比如,当文件大于128M(block默认值)而小于256M时,文件会被划分成两个spilt。

    2)文件的个数。FileInputFormat按文件进行分割,如果单个文件大于128M会被划分为多个spilt,反之,如果单个文件小于128M,FileInputFormat会把小文件单独划分成一个spilt。

    3)splitsize的大小。分片是按照splitsize的大小进行的,默认情况下,splitsize的大小等同于hdfs的block大小。但可以通过参数调节。

            InputSplit=Math.max(minSize,Math.min(max.Size,blockSize))

     其中:

            minSize = mapred.min.split.size

            maxSize = maperd.max.split.szie

    我们可以在MapReduce程序的驱动部分添加如下代码进行设置:

           TextInputFormat.setMinInputSplitSize(job,1204*64L) ; //设置最小分片大小

           TextInputFormat.setMinInputSplitSize(job,1204*64L); //设置最大分片大小

总结如下:

      当mapreduce.input.fileinputformat.split.maxsize > mapreduce.input.fileinputformat.split.minsize > dfs.blockSize的情况下,此时的splitSize 将由mapreduce.input.fileinputformat.split.minsize参数决定

      当mapreduce.input.fileinputformat.split.maxsize > dfs.blockSize > mapreduce.input.fileinputformat.split.minsize的情况下,此时的splitSize 将由dfs.blockSize配置决定

      当dfs.blockSize > mapreduce.input.fileinputformat.split.maxsize > mapreduce.input.fileinputformat.split.minsize的情况下,此时的splitSize将由mapreduce.input.fileinputformat.split.maxsize参数决定。

 

 

 

  其中TextInputFormat继承自FileInputFormat,FileInputFormat继承自InputFormat。

          InputFormat这个类会将文件file进行逻辑划分,划分成的每一个spilt对应一个map,在MR中运行

          FileInputFormat这个类先对输入文件进行逻辑上划分,以128M(hdfs block默认值)为单位,将原始数据从逻辑上分割成若干个split,每个split切片对应一个Mapper任务。要注意的是FileInputFormat这个类只对比HDFS Block大的文件进行划分,比HDFS Block小的文件不进行划分,此时的小文件会被当做一个split块并分配一个Mapper任务。这也是Hadoop处理大文件的效率要比处理很多小文件的效率高的原因。

            当FileInputFormat这个类将文件file切分成block块之后,TextInputFormat这个类随后将每个split块中的每行记录解析成一个一个的键值对,即

综上:我们可以简单理解为FileInputFormat这个类是将文件file切分成split块,而TextInputFormat这个类是负责将每一行记录解析为键值对

二、Reduce的个数

    Reduce任务是一个数据聚合的步骤,数量默认为1。而使用过多的Reduce任务则意味着复杂的shuffle,并使输出文件数量激增。而reduce的个数设置相比map的个数设置就要简单的多,只需要设置setNumReduceTasks即可.

 

下面是以WordCount为例的一个简单示范。

package hadoop;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;

import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

/**
 * Hadoop
 */
public class WordCountAPP {
    public static class MyMapper extends Mapper{
        @Override
        protected void setup(Context context) throws IOException, InterruptedException {
            System.out.println("setUp");
        }

        @Override
        protected void cleanup(Context context) throws IOException, InterruptedException {
            System.out.println("cleanUp");
        }

        @Override
        protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
                    String[] values = value.toString().split(",");

                    for (String s : values){
                        Text k = new Text(s);
                        context.write(k, new LongWritable(1));
                    }
        }
    }
    public static class MyReducer extends Reducer{
        @Override
        protected void reduce(Text key, Iterable values, Context context) throws IOException, InterruptedException {
                long sum = 0;
                for (LongWritable v : values){
                    sum += v.get();
                }
                context.write(key,new LongWritable(sum));
        }
    }


    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf,"wordcount");
        job.setJarByClass(WordCountAPP.class);

        if (args.length < 2){
            System.err.println("Please enter  and ");
        }
        Path outputPath = new Path(args[1]);
       // Path outputPath = new Path(args[1]);
        FileSystem fs = FileSystem.get(conf);
        if (fs.exists(outputPath)){
            fs.delete(outputPath,true);
            System.out.println("outputpath exists,delete!");
        }
        //FileInputFormat.setInputPaths(job,new Path(args[0]));
        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileInputFormat.setMinInputSplitSize(job,1024*1204*64L);
        FileInputFormat.setMaxInputSplitSize(job, 1204*64L);
        job.setMapperClass(MyMapper.class);
        job.setReducerClass(MyReducer.class);
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(LongWritable.class);

        job.setNumReduceTasks(2);

        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(LongWritable.class);

//        FileOutputFormat.setOutputPath(job,new Path(args[1]));
        FileOutputFormat.setOutputPath(job, outputPath);

        System.exit(job.waitForCompletion(true) ? 0: 1);
    }



}

    代码中设置的split大小为64M,切割文件大小为98M,运行结果如下:

 

 

 

 

 

你可能感兴趣的:(MapReduce中的Map,Reduce个数设定)