看了许久的代码,把map的流程熟悉了下,不追求最准确的理解,记录下来以免忘记。

   对于JobTracker和TaskTracker等大层面有控制和通讯的代码暂时不表

   map过程俗气的先上一个图:

mapreduce无reduce 无输出怎么设置 mapreduce的map_抽象类

map这一端基本是这样的流程:

input split分解成map个数量的部分输入==》RecordReader分解成Mapper需要的(key,value)记录==》执行map方法==》执行的结果起初在内存当中==》

当内存记录过多的时候spill到硬盘上面,如果有分区(Partitioner的话),spill的文件会记录分区的信息,单个spill文件首先按分区排序,然后按key排序==》

如果有多个spill文件则需要merge成一个大文件,是对spill文件的归并排序.

 

input split部分:

通过实现InputFormat抽象类中的两个方法就能达到效果。

getSplits(JobContext context),实现此方法,实现输入的切分,切分成map个数量的独立输入,这样每一个split都对应一个map

createRecordReader(InputSplit split,TaskAttemptContext context),实现此方法可以从split中读取到map需要的(key,value)对,当然类型需要和map方法的key,value参数类型一致

 

map方法:

map(KEYIN key, VALUEIN value, Context context),是对外提供的主要方法,一般只要实现此方法就可以实现MapReduce程序中的map过程,对输入(key,value)处理完之后,通过Context的方法写入到内存当中

 

spill,sort,merge:

当map方法被执行的次数过多,内存肯定是不够,所以此时需要持久化到硬盘里面去,此时就是spill的过程,在spill之前呢,其实是需要进行排序的也就是sort过程,sort过程首先按照分区进行排序,这样每个分区的数据排在一起,因为一个分区的数据是一个reduce过程的输入数据(确切的说是部分数据,因为map是有很多节点的,所有节点的分区数据之和才是reduce的输入),之后还需要按照key进行排序(每个分区之内的key),这样每个分区里面的key是有序的。排序以后就spill到硬盘当中。

当map过程都结束以后,spill到硬盘的文件数最起码有一个,一般都是多个,这个时候就需要merge了,merge的时候是个典型的归并排序,因为每个spill文件都是按照分区,然后按照分区中的key排序,所以merge过程是一个个分区的key进行归并排序的。

 

其他:

一般实现一个mapreduce程序的map端需要做的事情有:

 实现InputFormat,实现RecordReader,实现InputSplit,实现Mapper的map方法,如果有分区的话就实现Partitioner。对于性能方面的问题,另起一篇说明。