3

1 つの短い (<100 バイト) キーと 1 つの大きな (>1GB) 値 (BytesWriteable) を持つ大きな Hadoop SequenceFile を作成するさまざまな方法を試しました。

次のサンプルは、すぐに使用できます。

https://svn.apache.org/repos/asf/hadoop/common/trunk/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-jobclient/src/test/java/org/apache/ Hadoop/mapred/BigMapOutput.java

合計サイズが 3GB を超える複数のランダムな長さのキーと値を書き込みます。

しかし、それは私がやろうとしていることではありません。そこで、hadoop 2.2.0 API を使用して次のように変更しました。

      Path file = new Path("/input");
      SequenceFile.Writer writer = SequenceFile.createWriter(conf,
      SequenceFile.Writer.file(file),
      SequenceFile.Writer.compression(CompressionType.NONE),
      SequenceFile.Writer.keyClass(BytesWritable.class),
      SequenceFile.Writer.valueClass(BytesWritable.class));
      int numBytesToWrite = fileSizeInMB * 1024 * 1024;
      BytesWritable randomKey = new BytesWritable();
      BytesWritable randomValue = new BytesWritable();
      randomKey.setSize(1);
      randomValue.setSize(numBytesToWrite);
      randomizeBytes(randomValue.getBytes(), 0, randomValue.getLength());
      writer.append(randomKey, randomValue);
      writer.close();

fileSizeInMB>700MB の場合、次のようなエラーが発生します。

java.lang.NegativeArraySizeException
        at  org.apache.hadoop.io.BytesWritable.setCapacity(BytesWritable.java:144)
        at  org.apache.hadoop.io.BytesWritable.setSize(BytesWritable.java:123)
        ...

このエラーについて議論されていますが、解決策がありません。int(2^32) は 2GB まで大きくなる可能性があることに注意してください。700MB で失敗することはありません。

このような大きな値の SequenceFile を作成する別の方法がある場合は、アドバイスしてください。入力ストリームからバイト [] への IOutils.read などの他のアプローチを試してみたところ、ヒープ サイズまたは OOME が得られました。

4

2 に答える 2

1

代わりに ArrayPrimitiveWritable を使用してください。

ここでBytesWritableに新しい容量を設定すると、int オーバーフローが発生します。

public void setSize(int size) {
    if (size > getCapacity()) {
       setCapacity(size * 3 / 2);
    }
    this.size = size;
}

700 Mb * 3 > 2Gb = int オーバーフロー!

その結果、700 Mb を超えるデータを BytesWritable にデシリアライズすることはできません (ただし、書き込みとシリアライズはできます)。

于 2015-08-28T11:14:51.247 に答える
0

を使用するBytesWritable場合は、オプションで容量が十分に大きく設定されているため、700MB だけでなく 2GB を使用します。

randomValue.setCapacity(numBytesToWrite);
randomValue.setSize(numBytesToWrite); // will not resize now

このバグは最近 Hadoop で修正されたので、新しいバージョンではそれがなくても動作するはずです:

public void setSize(int size) {
  if (size > getCapacity()) {
    // Avoid overflowing the int too early by casting to a long.
    long newSize = Math.min(Integer.MAX_VALUE, (3L * size) / 2L);
    setCapacity((int) newSize);
  }
  this.size = size;
}
于 2016-06-04T14:29:12.047 に答える