(いくつかのロジックに従って) 分割してマッパーに配布する必要があるバイナリ ファイルのセットがあります。これにはHadoop ストリーミングを使用します。主な問題は、正確なバイナリ チャンクを変更せずにネットワーク経由で送信することです。raw バイトを送信するのは簡単ではないことが判明しました。
RecordReader
問題をよりよく説明するために、分割からいくつかのバイトを読み取って送信する非常に単純な拡張クラスを作成しました。バイナリ データには何でも含めることができます (改行文字を含む)。ここに何next()
を読むかもしれません:
public class MyRecordReader implements
RecordReader<BytesWritable, BytesWritable> {
...
public boolean next(BytesWritable key, BytesWritable ignore)
throws IOException {
...
byte[] result = new byte[8];
for (int i = 0; i < result.length; ++i)
result[i] = (byte)(i+1);
result[3] = (byte)'\n';
result[4] = (byte)'\n';
key.set(result, 0, result.length);
return true;
}
}
このシナリオでは、next()
関数を呼び出すたびに、次のバイト シーケンスを stdin: に書き込む必要があります01 02 03 0a 0a 06 07 08
。型指定されたバイト ( Hadoop-1722 ) を使用する場合、シーケンスには合計 5 バイトのプレフィックスを付ける必要があります。最初のバイトはシーケンスの型 (バイトの場合は 0)、残りの 4 バイトはサイズです。したがって、シーケンスは次のようになります00
00
00
00
08
01
02
03
0a
0a
06
07
08
。
結果を確認するためにテストしまし/bin/cat
た。コマンドは次のとおりです。
hadoop jar <streaming jar location>
-libjars <my input format jar>
-D stream.map.input=typedbytes
-mapper /bin/cat
-inputformat my.input.Format
hexdump
着信キーを表示するために使用すると、次のようになりました: . ご覧のとおり、すべての(改行) の前に(タブ) が付いていますが、入力されたバイトは、バイト シーケンスの型とサイズに関する (以前の) 正しい情報を提供します。00
00
00
00
08
01
02
03
09
0a
09
0a
06
07
08
0a
09
これは、バイトが途中で変更されるため、他の言語を使用してマッパーを作成する際に深刻な問題を引き起こします。
別のものがない限り、バイトがそのまま送信されるという保証はないようです。