map端相对于client端就会复杂很多,里面包含了map的读入,重新赋值,输出等过程,
入口为;mapTask的run方法,因为我自己使用的是2.6.5的版本所以是使用的newapi,此处需要注意的地方是,如果reduce的个数为0的话,就不会设置排序的过程,之后还会有根据reduce的个数进行双向选择的地方,此处需要注意
@Override
public void run(final JobConf job, final TaskUmbilicalProtocol umbilical)
throws IOException, ClassNotFoundException, InterruptedException {
this.umbilical = umbilical;
if (isMapTask()) {
// If there are no reducers then there won't be any sort. Hence the map
// phase will govern the entire attempt's progress.
//判断reduce的个数。默认reduce的个数为1个
if (conf.getNumReduceTasks() == 0) {
mapPhase = getProgress().addPhase("map", 1.0f);
} else {
// If there are reducers then the entire attempt's progress will be
// split between the map phase (67%) and the sort phase (33%).
mapPhase = getProgress().addPhase("map", 0.667f);
//增加排序阶段-》排序结果-》内部有序外部无序--》reduce性能的提升
sortPhase = getProgress().addPhase("sort", 0.333f);
}
}
TaskReporter reporter = startReporter(umbilical);
boolean useNewApi = job.getUseNewMapper();
//初始化job
initialize(job, getJobID(), reporter, useNewApi);
// check if it is a cleanupJobTask
if (jobCleanup) {
runJobCleanupTask(umbilical, reporter);
return;
}
if (jobSetup) {
runJobSetupTask(umbilical, reporter);
return;
}
if (taskCleanup) {
runTaskCleanupTask(umbilical, reporter);
return;
}
if (useNewApi) {
runNewMapper(job, splitMetaInfo, umbilical, reporter);
} else {
runOldMapper(job, splitMetaInfo, umbilical, reporter);
}
done(umbilical, reporter);
}
接下来的这个方法中将进行map相关的基本上所有的重要流程;
/**
* 这个方法的作用;
* 初始化任务的上下文-》包含job相关的信息
* 初始化切片-》该map所要处理的切片是哪一个-》切片决定map的个数,有多少个切片就会有多少个map去执行
* 初始化读取器-》切片中的内容是以什么样格式被读到内存中去-》里面涉及的有;
* 获取切片所归属的位置信息
* 根据该map所持有的切片的位置信息和偏移量,决定归属的文件,打开文件,seek到偏移量的位置开始读取
* 进而完成计算像数据移动
* 此处需要注意的是;
* 如果该切片不是第一个切片,切片相关信息中有切片的索引值,就会抛弃首行,从第二行开始读取,并把下一个切片的首行读进来
* 初始化mapper;
* 此处是需要我们去重新定义的,定义map输出的key,value的格式和类型,如果不重写的话,会导致沿用默认的mapper,输出从文件重获取的k,v的值,没有实际意义
* 此处是必须重写的地方
* 初始化output;
* 两个方式
* 如果没有reduce过程-》初始化直接输出的output
* 如果存在reduce过程-》初始化一个NewOutputCollector-》
* 初始化一个可排序的环形缓冲区-》100m,0.8时发生溢写
* 当发生溢写的时候同时会发生排序,排序时先按分区排序,再按key排序
* 如果没有自定义排序比较器的话,会按照key值所属的类型的比较器去进行比较
*
*
*/
&#