这篇文章记录一下自己对Hadoop输入格式的理解。详细参考hadoop API org.apache.hadoop.mapreduce 以及org.apache.hadoop.mapreduce.input.lib 包。

  

mapreduce shuffle落盘 mapreduce inputformat_大数据

                                                     图一:InputFormat类结构

  以上是hadoop输入部分用到的类的结构层次图(注:改图是根据旧版API画,类所在的包显示的均是就版API中所在,我在学习时均使用新版API,贴出此图为了直观的理解)。

InputFormat(org.apache.hadoop.mapreduce)

  从上图可以看出,最上层是一个InputFormat接口,它描述MapReduce Job的输入。以下是API中对InputFormat类的解释:

mapreduce shuffle落盘 mapreduce inputformat_hadoop_02

                                                                              图 二  InputFormat 解释

mapreduce shuffle落盘 mapreduce inputformat_数据库_03

                                                                               图 三 InputFormat 方法总结

  即通过InputFormat,hadoop可以实现:

1.检查MapReduce输入数据的正确性。2.将数据数据切分为逻辑分片InputSplit,分片分配给Mapper,一个分片只能够被单个map操作处理,每个map操作也只处理一个数据分片。3.提供一个RecorReader的实现,Mapper用改实现从InputSplit中读取<k,v>对。

  Hadoop可以处理很多格式的数据,从一般的文件到数据库数据等,所以从图一的第二层可以看到有FileInputFormat,DBInputFormat。

FileInputFormat(org.apache.hadoop.mapreduce.lib.input)

  FileInputFormat是所有以文件作为数据源的InputFormat的实现。它保存job输入的所有文件,并实现为文件计算split的方法。至于如何读取记录(RecordReader),不同的子类有不同的实现方法。下图是API中对FileInputFormat类的解释:

mapreduce shuffle落盘 mapreduce inputformat_数据库_04

                                                                        图 四 FileInputFormat 类解释

  FileInputFormat类的方法有很多,详细可以查看API,至于FileInputFormat如何划分split,它只划分比HDFS block(默认64M大小)大的文件,如果一个文件比block块小,它不会被划分,这也是hadoop处理大文件比处理小文件效率高的原因。

  FileInputFormat类有很多子类,比较重要的是TextInputFormat类和SequenceFileInputFormat类。这里主要说一下这两个类,其他的可以查看《Hadoop权威指南》和最后给的参考资料。

TextInputForamt(org.apache.hadoop.mapreduce.lib.input)

  Hadoop默认的输入方式是TextInputFormat,它重写了FileInputFormat的creatRecordReader和isSplit方法。createRecordReader( )方法返回的是LineRecordReader对象(),该对象读取记录时是按行读取,以回车键和换行符为行分割符。key为行开始位置的偏移量,value为该行的内容。

  当然有时这种读取记录的方式并不能满足你的要求,有时候你不想用回车或换行作为分割符,而是有自己特殊的行分割符,这时你要重写一个InputFormat 重写的类继承FileInputFormat,参考资料其中之一讲到如何重写InputFormat类。

SequenceFileInputFormat(org.apache.hadoop.mapreduce.lib.input)

  SequenceFileInputFormat存储二进制键/值对的序列。如果在MapReduce中使用顺序文件,就必须使用改输入方式。它重载了listStatus,实现了createRecordReader方法返回一个SequenceFileRecordReader对象。下面是API中该类的方法:

mapreduce shuffle落盘 mapreduce inputformat_hadoop_05

                                                 图 五 SequenceFileInputFormat 方法总结

  TextInputFormat和SequenceFileInputFormat中都实现了createRecordReader类,该类要返回一个RecordReader对象。很多时候我们要自己定义InputFormat类,在InputFormat类中写自己需要的读取记录的方式即RecordReader对象,下面就RecordReader做简单的解释。

RecordReader(org.apache.hadoop.mapreduce)

  RecordReader用于在划分中读取<Key,Value>对。RecordReader有五个虚方法,分别是:

      initialize:初始化,输入参数包括该Reader工作的数据划分InputSplit和Job的上下文context;

      nextKey:得到输入的下一个Key,如果数据划分已经没有新的记录,返回空;

     nextValue:得到Key对应的Value,必须在调用nextKey后调用;

     getProgress:得到现在的进度;

     close,来自java.io的Closeable接口,用于清理RecordReader。

mapreduce shuffle落盘 mapreduce inputformat_大数据_06

                                         图 六 RecordReader 方法总结

  当然要具体弄明白RecordReader类还是建议找个例子的代码或Hadoop中LineRecordReader类的源码分析一下。

  还有很多输入方式没说,自己也还没弄清楚,感兴趣的可以自己去查资料。自己小总结一下:也就是hadoop的输入文件要通过***InputFormat 类来将文件分片,可以自己设定是否分片以及分片规则isSplitable()/getSplits,然后要有一个RecordReader对象来读取记录,改RecordReader对象读取记录是要实现图六中的方法。最后就会按需要的<K,V>对方式 输送个Mapper。

具体可以查询下面的参考资料。

参考资料:

       《Hadoop权威指南》

         Hadoop-0.20 API