在Hadoop MapReduce中为二进制文件创建自定义InputFormat和RecordReader

时间:2012-05-10 09:20:28

标签: hadoop mapreduce binaryfiles input-split

我正在编写一个M / R作业来处理以二进制格式编写的大型时间序列数据文件,看起来像这样(这里的新行是为了便于阅读,实际数据显然是连续的):

TIMESTAMP_1---------------------TIMESTAMP_1
TIMESTAMP_2**********TIMESTAMP_2 
TIMESTAMP_3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%TIMESTAMP_3
.. etc

其中timestamp只是一个8字节结构,可由前2个字节识别。实际数据在重复值时间戳之间有界,如上所示,并包含一个或多个预定义结构。我想编写一个自定义的InputFormat,它将向映射器发出键/值对:

< TIMESTAMP_1, --------------------- >
< TIMESTAMP_2, ********** >
< TIMESTAMP_3, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% >

逻辑上,我想跟踪当前TIMESTAMP,并汇总所有数据,直到再次检测到TIMESTAMP,然后发送我的<TIMESTAMP, DATA>对作为记录。我的问题是在RecordReader内的拆分之间进行同步,因此如果某个读者收到以下拆分

# a split occurs inside my data
reader X: TIMESTAMP_1--------------
reader Y: -------TIMESTAMP_1 TIMESTAMP_2****..

# or inside the timestamp
or even: @@@@@@@TIMES
         TAMP_1-------------- ..

有什么好方法可以解决这个问题?我是否有一种简单的方法来访问文件偏移量,以便我的CustomRecordReader可以在分割之间同步而不会丢失数据?我觉得我在如何处理分割方面存在一些概念上的差距,因此对这些分析可能有所帮助。感谢。

2 个答案:

答案 0 :(得分:3)

通常,创建支持拆分的输入格式并不简单,因为您应该能够找到从拆分边界移动的位置以获得一致的记录。 XmlInputFormat就是格式化的好例子。
我建议首先考虑一下你是否确实需要可拆分输入?您可以将输入格式定义为不可拆分,并且不会出现所有这些问题。
如果你的文件通常不比块大小大 - 你什么都没有丢失。如果他们这样做 - 您将丢失部分数据位置。

答案 1 :(得分:2)

您可以继承FileInputFormat的具体子类,例如SeqenceFileAsBinaryInputFormat,并覆盖isSplitable()方法以返回false

import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.mapred.SequenceFileAsBinaryInputFormat;

public class NonSplitableBinaryFile extends SequenceFileAsBinaryInputFormat{

  @Override
  protected boolean isSplitable(FileSystem fs, Path file) {
      return false;
  }

  @Override
  public RecordReader getRecordReader(InputSplit split, JobConf job,
  Reporter reporter) throws IOException {
    //return your customized record reader here
  }
}