Hadoop FileInputFormat实现原理及源码分析

FileInputFormat(org.apache.hadoop.mapreduce.lib.input.FileInputFormat)是专门针对文件类型的数据源而设计的,也是一个抽象类,它提供两方面的作用:
 
(1)定义Job输入文件的静态方法;
(2)为输入文件形成切片的通用实现;
 
至于如何将切片中的数据转换为一条条的“记录”则根据文件类型的不同交由具体的子类负责实现。
 
FileInputFormat input paths
 
FileInputFormat提供了四个静态方法用于定义Job的输入文件路径:
 
public static void addInputPath(Job job, Path path)
public static void addInputPaths(Job job, String commaSeparatedPaths)
public static void setInputPaths(Job job, Path... inputPaths)
public static void setInputPaths(Job job, String commaSeparatedPaths)
 
addInputPath()、addInputPaths()用于“添加”一个(批)输入路径,可以重复被调用,源码如下:
 
 
addInputPath的每一次调用都会将输入路径(Path会被转换为字符串形式)与原有值以“,”分隔进行拼接(并不会覆盖原有值),并保存至Job Configuration的属性INPUT_DIR(mapreduce.input.fileinputformat.inputdir)中。
 
 
而addInputPaths实际是对addInputPath的循环调用。
 
setInputPaths()实际是两个重载方法,用于“设置”一个(批)输入路径,该方法用于一次性调用,每一次调用都会覆盖之前的结果,源码如下:
 
 
该方法的最后会替换Job Configuration属性INPUT_DIR(mapreduce.input.fileinputformat.inputdir)的原有值。
 
 
 
这里所说的输入路径可以代表一个文件,也可以代表一个目录(该目录下的所有文件将全部作为输入数据),而且可以在输入路径中使用通配符或者使用“,”进行多个输入路径的拼接。
 
注意:目录中的内容(子目录)不会被递归处理。实际上目录中应仅包含文件,如果目录中包含子目录,这些子目录会被当作文件处理,从而引发异常。如果我们不需要递归目录,我们可以通过File Pattern或者Filter(见后)告知FileInputFormat仅仅选取指定目录中的文件;如果我们确实需要递归处理目录,则可以通过设置mapreduce.input.fileinputformat.input.dir.recursive为true实现。
 
有些时候我们还需要“过滤”输入路径中的一些文件,这可以通过方法setInputPathFilter()为FileInputFormat设置相应的过滤器实现,源码如下:
 
 
实际就是指定一个PathFilter(PathFilter的相关内容不再讨论范围)的具体实现类名称,保存于Job Configuration属性PATHFILTER_CLASS(mapreduce.input.pathFilter.class)中。
 
如果我们没有显示设置PathFilter,FileInputFormat会有一个默认的过滤器,用于过滤目录中的隐藏文件;如果我们显示设置PathFilter,则FileInputFormat的过滤器实则是一个过滤器链,而默认的过滤器会居于过滤器链的首部,优先被执行。
 
综上所述,FileInputFormat的输入路径和过滤器实际可以直接通过相应的属性值进行设置,如下图所求:
 
 
FileInputFormat input splits
 
FileInputFormat生成切片的过程是由getSplits()方法实现的,核心逻辑及相关源码如下:
 
1. 确定切片大小的最小值与最大值;
 
 
最小值:getFormatMinSplitSize()与getMinSplitSize()两者之间的较大值。getFormatMinSplitSize()是FileInputFormat中的一个实例方法,默认返回值为1,即1字节;getMinSplitSize()返回值由属性mapreduce.input.fileinputformat.split.minsize决定,默认值为1,即1字节。如果没有特殊需要,最小值即为1字节。有些数据格式的文件对切片的最小大小是有要求的,如SequenceFile(具体可参考SequenceFile相关文档),这时就需要在FileInputFormat子类中重写getFormatMinSplitSize()方法来满足特定需求。
 
最大值:getMaxSplitSize()返回值由属性mapreduce.input.fileinputformat.split.maxsize决定,默认值为Long.MAX_VALUE。
 
2. 获取输入路径中的所有文件信息;
 
 
3. 迭代处理输入路径中的每一个文件,为每一个文件生成切片;
 

你可能感兴趣的:(Hadoop FileInputFormat实现原理及源码分析)