输入前的过程是这样的:
1. JobClient调用getSplits方法以期望的map任务数numSplits作为参数传入,这个参数将作为一个参考值,因为InpFutormat实现可以自由地返回另一个不同于numSplits制定值得分片数。
2.在计算好分片数后,客户端将分片们发送到jobtracker,jobtracker便使用其存储位置信息来调度map任务(具体该距离最近的map来处理)从而在tasktracker上处理这些分片数据。
具体细节:在tasktracker上,map任务把输入分片传给InputFormat的getRecordReader()方法来获得这个分片的RecordReader。map任务用一个RecordReader来生成键值对,然后再给map函数。
RecordReader基本就是记录上的迭代器,他的next()方法反复调用以便为mapper生成键值对,当RecordReader到达输入流的尾部时,next()方法返回false,map任务结束。
二 、这里我们主要理解(上面第2步):
首先,我们要明白,在tasktracker上map任务会把 分片数据记录先输入到实现接口InputFormat的具体子类。这个类传递自身的一些有价值的东西,作为实现接口RecordRecorder的子类的构造函数参数,获得一个RecordRcord类的一个实例。
然后,我们的map任务就可以利用RecordReader类的实例调用这个类的方法。包括.createkey(),createvalue(),next()等等
图形表示:
注: (1)Runner类内部关键代码:K key=reader.createKey();
V value=reader.createValue();
while(reader.next(key,value))
{
mapper.map(key,value,output,reporter);
}
(2)InputFormat接口
public interface InputFormat<K,V> {
InputSplit [ ] getSplits(JobConf job,int numSplits) throws IOException; //主要负责第一步产生分片
RecordReader <K,V> getRecordReader(InputSplit split,JobConf job,Re