1、任务切分:对文件进行逻辑切片,切片按照范围划分,默认128M一片。
一个文件至少有一个切片,每个切片运行一个maptask,如果文件超过128M,同一个输入文件会有多个maptask运行;为减少资源浪费,如果最后一个切片大小小于1.1*128M,将不会被切分处理。
2、输入对象:FileInputFormat.setInputPaths()方法,指定数据输入路径;输入目录中可以有单个或多个文件。
读取数据、生成K-V对:由继承RecordReader的LineRecordReader类中的readLine()方法从输入的切片中读取数据;每读取一行执行一次,生成一组K-V。
3、map()方法:以单词统计为例,自定义的WordCountMapper类继承父类Mapper,接收K-V对,重写map()方法的业务逻辑。
map()的业务逻辑中,对数据进行切分,遍历数组,生成新的K-V对;由context.write(nk,nv)方法输出新的K-V。
map()方法执行时机:一对K-V执行一次。
4、map()的输出:context.write()被调用时,OutputController组件会将新的K-V输出到数组缓存区,写入数组缓存区中的还有新K-V的元数据;
5、KV分区:
MapOutputBuffer类调用collect(nk,nv,partition)方法接收新K-V;partition调用HashPartitioner组件;
HashPartitioner.getPartition(nk,nv){
nk.hashcode%numberReduceTasks;
}
获得分区,得到区号,返回给partition。
6、区内排序:①按照分区排序;②区内数据再按照K进行排序。
7、溢出:spiller,当缓冲区中的数据到达80%时,进行分区、排序,将数据溢出,当前处于阻塞状态,防止写入数据。(根据数据量大小溢出,至少一次)
8、归并、区内排序:将数组缓冲区中分区排序完的数据,用Merger组件进行归并,写入磁盘;同时进行区内排序。
9、局部聚合:调用Combiner组件,根据相同K进行数据聚合。
10、写入本地磁盘:将归并排序完成的数据写入本地磁盘,此阶段提供http下载,便于数据传输。
11、拉取数据:reducetask分别拉取属于自己的数据(本地–>分区经由网络传输)
12、归并排序:调用Merger组件,按照K进行排序。
13、分组:调用GroupingComparator组件中的CompareTo(preK,postK)方法,将相同K的分到一组,放入同一迭代器中。
14、聚合:reduce(K,iterator<>,context)方法中将相同K的数据进行聚合操作,聚合一次得到一组K-V。
15、输出:由TextOutputFormat的write方法,写出到HDFS(或本地磁盘)。