MapReduce工作原理的步骤解析

MapReduce工作原理的步骤解析

1、当maptask启动之后,InputFormat也就被启动了,用默认的TextInputFormat类型的RecordReader方法读取文件。这种方式的目的是:(1)数据切分:按照一行一行地分成若干个split,以便确定MapTask个数以及对应的split。(2)为Mapper提供输入数据:读取给定的split的数据,解析成一个个的(key:行的偏移量/value:读取到的行的内容),供Mapper使用。

2、mapper的map方法入口会得到map(k,v),并且进行逻辑计算处理形成新的map(k,v),并输出到OutPutCollector收集器

3、OutPutCollector负责收集mapper发出的数据,当map里的内容收集完毕后,再逐条发送给环形缓冲区

4、环形缓冲区默认大小为100M,采用先进先出机制,当环形缓冲区到达80%时,会触发spill溢出。这时,先存进的数据就先输出,输出的同时也在读取数据,读取到的数据就会覆盖在前面的数据上,直至读取完OutPutCollector收集器的数据。

5、spill溢出前需要对数据进行分区计算(HashPartitioner)和排序,相同partition值为同一分区,然后会把环形缓冲区中的数据来按照partition值排序、同一partition内的按照key排序。(如果采用Combiner方法,则会在同一个分区块下,相同key值进行局部的value合并。如:a1,a1,a1,a1,a1,a1就会写成a6)
(1)HashPartitioner分区规则:
HashPartitioner的getPartition方法返回值是int类型的,每条数据都要进来计算一下数据的分区,然后给每条数据打上一个逻辑标识,计算每一条数据要去哪一个reduceTask里去。
逻辑编号:(key.hashCode() & Integer.MAX_VALUE) % numberReduceTasks
因为key.hashCode()有可能是负数,所以要&Integer.MAX_VALUE,这样就永远是一个正整数。&按位与。
numberReduceTasks指多少个reduceTask。
(2)因为在同一个分区块下,同一个键得到的getPartition的返回值是一样的,所以同一个键会进同一个reducer

6、将环形缓冲区中排序后的内存数据不断地spill溢出,如果map阶段处理的数据量较大,可能会溢出多个文件;

7、多个溢出文件会被merge合成溢出的大文件,合并采用归并排序。这个大文件是mapTask最终结果,并且是分区的、区内有序的。(如果采用Combiner方法,则要把不同分区块下,相同key值进行局部的value合并)

8、等所有的DateNode都完成MapTask后,RreduceTask会根据自己的分区号,去各个mapTask节点上拷贝相同partition的数据到reduceTask

9、reduceTask会把来自不同mapTask的、但同一分区的结果文件,再进行merge合并成一个大文件(归并排序),大文件内容按照key排序(如果采用Combiner方法,只需要把不同分区块的相同(key,value)归并,不需要相加)

10、合并成大文件后,后面进入reduceTask的逻辑运算过程

11、最后通过OutputFormat方法将结果数据写到part-r-000""结果文件中

Shuffle:
MapReduce计算模型一般包括两个重要的阶段:Map是映射,负责数据的过滤分发;Reduce是规约,负责数据的计算归并。Reduce的数据来源于Map,Map的输出即是Reduce的输入,Reduce需要通过Shuffle来获取数据。 从Map输出到Reduce输入的整个过程可以广义地称为Shuffle(步骤4~步骤9)。Shuffle横跨Map端和Reduce端,在Map端包括Spill过程,在Reduce端包括copy和sort过程

WordCount案例

public class WordMapper extends Mapper<LongWritable, Text,Text, IntWritable> {
    //LongWritable, Text(输入类型,行号和每一行内容),Text, IntWritable(输出类型)
    private Text word = new Text();
    private IntWritable count = new IntWritable(1);

    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        String[] words = value.toString().replaceAll(",|\"|\\.|\\?|!|:|;","").split(" ");
        for (String _word : words) {
            word.set(_word);
            //向reducer传输内容
            context.write(word,count);
        }
    }
}

public class WordReducer extends Reducer<Text, IntWritable,Text,IntWritable> {
    private IntWritable count = new IntWritable(0);

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

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

        //创建HDFS访问路径配置信息
        Configuration config = new Configuration();
        config.set("fs.defaultFS","hdfs://192.168.37.200:9000");
        //创建mapreduce计算任务
        Job job = Job.getInstance(config,"wordCount");
        //设置主类,定位外部jar资源
        job.setJarByClass(WordTest.class);
        //设置任务数:和文件分片数和所存储的DN数有关
        job.setNumReduceTasks(2);
        //设置分区器Partitioner
        job.setPartitionerClass(WordPartitioner.class);
        //设置Combiner
        job.setCombinerClass(WordReducer.class);
        //设置mapper
        job.setMapperClass(WordMapper.class);
        //设置reducer
        job.setReducerClass(WordReducer.class);
        //设置mapper输出键值类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);
        //设置reducer输出键值类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
        //设置HDFS输入文件绑定job
        FileInputFormat.setInputPaths(job,new Path("/kb10/Pollyanna.txt"));
        FileOutputFormat.setOutputPath(job,new Path("/kb10/wordCount2"));
        //等待所有job步骤完成
        System.out.println(job.waitForCompletion(true));
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值