1

私はHadoopの初心者です。一度に3行を読み取り、3行の入力がマッパーに与えられた回数を出力するこのカスタムRecordReaderプログラムに出くわしました。

RecordReader が使用される理由は理解できますが、入力形式クラスが基本的に mapreduce.TextInputFormat クラスを拡張している場合に、各 InputSplit に 3 行を含める方法を確認できません。そして、私の理解によると、TextInputFormat クラスは各行 (各 \n) に対して 1 つの InputSplit を発行します。

では、RecordReader はどのようにして各 InputSplit から 3 行を読み取ることができるのでしょうか? これがどのように可能かを誰かが説明してください。前もって感謝します!

4

1 に答える 1

4

TextInputFormat答えを見つけるには、 の実装を理解する必要があります。

コードに飛び込みましょう。新しい mapreduce API について話しますが、「古い」mapred API は非常に似ています。

あなたが言ったように、ユーザーの観点からは、TextInputFormatいくつかの改行文字に従って分割をレコードに分割します。実装を確認しましょう。

クラスがほとんど空であることがわかります。重要な機能は、次のcreateRecordように定義されています。InputFormat

@Override
public RecordReader<LongWritable, Text> createRecordReader(
        InputSplit split, 
        TaskAttemptContext context
) {
   return new LineRecordReader();
}

一般的な契約では、InputFormat を使用して RecordReader を取得します。内部MapperMapContextImpl見ると、マッパーが RecordReader のみを使用して次のキーと値を取得していることがわかります。彼は他に何も知りません。

マッパー:

public void run(Context context) throws IOException, InterruptedException {
  setup(context);
  while (context.nextKeyValue()) {
    map(context.getCurrentKey(), context.getCurrentValue(), context);
  }
  cleanup(context);

}

MapContextImpl:

@Override
public boolean nextKeyValue() throws IOException, InterruptedException {
  return reader.nextKeyValue();
}

あなたが提供したこのリンクを注意深く読み直してください。次のことがわかります。

  • NLinesInputFormat拡張TextInputFormatし、オーバーライドのみを行います createRecordReader。基本的に を使用するのではなくLineReader、独自の を提供しますRecordReaderTextInputFormat階層の上位にある別のクラスではなく、拡張する必要があります。これは、このレベルで行われ、必要になる可能性のあるすべての処理が既に行われているためです (圧縮、分割不可能な形式など)。
  • NLinesRecordReader本当の仕事をします。これは、提供された から正しいオフセットでシークinitializeを取得するために必要なことを行います。また、によって使用されるものと同じものを作成しますInputStreamInputSplitLineReaderTextInputFormat
  • このnextKeyValueメソッドでは、3 つの行を取得するために 3 回呼び出されることがわかりますLineReader.readLine()(さらに、大きすぎるレコード、行末、分割の終わりなどのコーナー ケースを適切に処理するロジックもあります)。

それがあなたを助けることを願っています。重要なのは、API の全体的な設計と、各部分がどのように相互作用するかを理解することです。

于 2014-08-16T13:27:11.730 に答える