Hadoop中split数量计算法则(源码跟踪)

 

  从前面的文章(MapReduce运行原理【源码跟踪】)我们知道计算切片的部分在JobSubmitter类中,然后我们看此类的Structure(在idea中View->Tool Windows ->Structure)查看类结构我们很轻易的就能找到有关split的方法

我们可以在writeSplits方法中打一个断点,随便运行一个计数程序Debug跟踪查看。

这里给出一下计数程序

WCmapper

 1 package com.qin.MapReduce;
 2 
 3 import org.apache.hadoop.io.IntWritable;
 4 import org.apache.hadoop.io.LongWritable;
 5 import org.apache.hadoop.io.Text;
 6 import org.apache.hadoop.mapreduce.Mapper;
 7 
 8 import java.io.IOException;
 9 
10 public class WCMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
11 
12     protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
13         Text outText = new Text();
14         IntWritable valueOut = new IntWritable();
15         String[] split = value.toString().split(" ");
16         for (String  str: split ){
17             outText.set(str);
18             valueOut.set(1);
19             context.write(outText,valueOut);
20         }
21     }
22     
23 }

WCreducer

package com.qin.MapReduce;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;


public class WCreducer extends Reducer<Text, IntWritable, Text, IntWritable>{

    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
        int count = 0;
        for (IntWritable value : values){
            count = value.get() + count;
        }

        context.write(key, new IntWritable(count));
    }
}

WCapp

package com.qin.MapReduce;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
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;

public class WCapp {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {

        Configuration conf = new Configuration();
        conf.set("fs.defaultFS","file:///");

        Job job = Job.getInstance(conf);
        //Job的各种属性
        job.setJobName("WCapp");        //设置作业名称
        job.setJarByClass(WCapp.class); //设置搜索类
        job.setInputFormatClass(TextInputFormat.class);

        job.setMapperClass(WCMapper.class);
        job.setReducerClass(WCreducer.class);

        job.setNumReduceTasks(1);

        //添加输入路径
        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job,new Path(args[1]));

        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);

        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
        job.waitForCompletion(true);   //是否打印出详细信息

    }
}

Debug运行以后,Step over到 maps = this.writeNewSplits(job, jobSubmitDir);的地方时

我们Step Into进去看看

多次Step over到 List splits = input.getSplits(job);我们再次Step into

这里我们看见minSize是取两个参数中最大值。我们通过鼠标放在某个参数上Alt+鼠标左键看属性的详细定义,知道this.getFormatMinSplitSize()的值为1,

getMinSplitSize(job)是得到配置文件mapred-default.xml中的mapreduce.input.fileinputformat.split.minsize的值

默认配置图如下

所以minSize的值为1

 然后我们在step over 然后step into到getMaxSplitSize(job)中

我们很容易就知道maxSize是long型的最大值

maxSize=9223372036854775807L

继续向下看

这里我们知道blockSize1在得到块大小。

blockSize1 = 33554432

进入到this.computeSplitSize()中看它是如何计算得到splitSize的

blockSize1 maxSize blockSize我们都得到了

一分析computeSplitSize方法,我们知道得到的是三个值的中间值

总结:默认情况下,切片大小跟块大小是一样大

 切片大小跟块大小一样的好处:

  如果我们定义splitSize是1M,那么一块128M,切成128个split,分发到网络上128个结点同时运行(可以一个结点运行多个切片,但是集群并发情况下,负载均衡,系统会自动分发给其它结点),浪费时间与资源。

  如果我的splitSize和块大小相同,直接就在本结点上运行了(nodemanage的本地优先策略)。

猜你喜欢

转载自www.cnblogs.com/qincan4Q/p/9806192.html
今日推荐