概述
InputFormat描述了MapReduce Job的输入规范。
Map-Reduce框架依赖作业的InputFormat完成如下工作:
1.验证作业的输入规范;
2.将输入文件拆分为逻辑 InputSplits,然后将每一个分片分配给一个独立的 Mapper;
3.提供 RecordReader 的实现,用于从逻辑 InputSplit 中收集输入记录,供 Mapper 处理。
基于文件的 InputFormats (通常是 FileInputFormat 的子类)的默认行为是根据输入文件的总大小(以字节为单位)将输入拆分为逻辑InputSplits。但是,输入文件的 FileSystem 块大小被视为InputSplits 的上限。可以通过 mapreduce.input.fileinputformat.split.minsize。设置分片大小的下限。
显然,基于输入大小的逻辑拆分对于许多应用程序来说是不够的,因为需要考虑记录边界。在这种情况下,应用程序还必须实现一个RecordReader,它负责处理记录边界( record-boundaries),并将面向记录的逻辑 InputSplit 视图提交给单个任务。
InputSplit
从上面的描述可知,InputFormat 的主要工作就是将输入数据分割为一个个的 InputSplit。InputSplit是一个抽象类,其定义如下:
public abstract class InputSplit {
public abstract long getLength() throws IOException, InterruptedException;
public abstract
String[] getLocations() throws IOException, InterruptedException;
@Evolving
public SplitLocationInfo[] getLocationInfo() throws IOException {
return null;
}
}
抽象类 InputSplit 有三个方法,getLength 用以获取 InputSplit 的大小,这样 InputSplit 就可以按照大小进行排序。getLocations 用以获取存储分片的节点列表,而 getLocationInfo 用以获取关于InputSplit存储的节点以及其是如何在每个位置存储的相关信息。
InputFormat
了解了 InputSplit 的基本构造,我们来看看 InputFormat 的定义,如下:
public abstract class InputFormat<K, V> {
public abstract
List<InputSplit> getSplits(JobContext context
) throws IOException, InterruptedException;
public abstract
RecordReader<K,V> createRecordReader(InputSplit split,
TaskAttemptContext context
) throws IOException,
InterruptedException;
}
抽象类 InputFormat 有两个方法,getSplits 用以获取将输入文件进行split后的分片列表。注意,这里所谓的分片只是逻辑的,输入文件并不会被物理的拆分。比如一个分片可能是由 <input-file-path,start,offset> 这样的tuple构成。InputFormat 将会创建RecordReader来读取分片。createRecordReader 方法,顾名思义,就是用来创建 RecordReader 的。
InputFormat 有很多的实现类,下面是InputFormat类继承结构图,其中最常用的是 FileInputFormat及其子类(TextInputFormat、SequenceFileInputFormat)
参考:
http://hadoop.apache.org/docs/stable/api/org/apache/hadoop/mapred/InputFormat.html
https://blog.csdn.net/diyibeichaaixiaoyu/article/details/25043445