- MapReduce作业通常将输入数据集分割成独立的块,由map任务以完全并行的方式处理。
- 框架对映射的输出进行排序,然后将这些输出输入到reduce任务中。通常,作业的输入和输出都存储在文件系统中。框架负责调度任务,监视它们并重新执行失败的任务
- 简单的说,mapreduce指定输入/输出位置和供应映射,并通过适当的接口和/或抽象类的实现来减少功能。这些和其他工作参数组成了作业配置。
输入和输出
- MapReduce框架只对
<key, value>对
进行操作,也就是说,框架将输入的输入一组键值对,输出也是键值对。key
,value
类是可串行化的,因此要实现writable接口
,另外,框架也需要实现WritableComparable接口
来帮助排序。输入和输出的样式是这这样的:
public void map(Object key, Text value, Context context
) throws IOException, InterruptedException {
StringTokenizer itr = new StringTokenizer(value.toString());
while (itr.hasMoreTokens()) {
word.set(itr.nextToken());
context.write(word, one);
}
}
输入的文件
Hello World Bye World
hadoop运行时调用的Mapper接口
通过我们写的map函数,每次产生一行,具有特定的的TextInputFormat
输入格式。然后通过,StringTokenizer
,把这行分成字符,以空格键为标志,产生一个键值对< < word >,1>
补充下,TextInputFormat
的源码:
public class TextInputFormat extends FileInputFormat<LongWritable, Text> {
public TextInputFormat() {
}
public RecordReader<LongWritable, Text> createRecordReader(InputSplit split, TaskAttemptContext context) {
return new LineRecordReader(recordDelimiterBytes);
}
}
从上面可以看到,有一个公共方法,createRecordReader
,这个方法的作用是为Mapper提供输入数据:读取给定的split的数据,解析成一个个的key/value对,共Mapper使用。
LineReader和LineRecordReader
我们仔细研究后,发现createRecordReader
实现输出文件key,value
是通过LineReader和LineRecordReader
这个具体的类的。这里我们就来说一说这个RecordReader
这个类吧
RecordReader是抽象类,LineRecordReader是实现类,RecordReader有很多子类,例如LineRecordReader
,SequenceFileRecordReader
,KeyValueLineRecordReader
等,里面的方法实现不一样,如nextKeyValue()
方法。
系统默认的RecordReader
是LineRecordReader
,如TextInputFormat
;而SequenceFileInputFormat
的RecordReader
是SequenceFileRecordReader
。
总结
RecordReader(interface), LineRecordReader(class)的关系如下:
- FileInputFormat(抽象类) implements InputFormat(接口)
- TextInputFormat(具体实现) extends FileInputFormat
- TextInputFormat.getRecordReader calls LineRecordReader //(这里是默认的)
- LineRecordReader implements RecordReader,即RecordReader是抽象类,LineRecordReader是实现类。