Kryo内存不足

时间:2015-06-25 20:20:12

标签: apache-spark kryo

无论我尝试了什么,我在使用Kryo序列化程序时都会使用Spark 1.3.1获取此OOME(如果我使用默认的Java,我不会遇到任何问题)

15/06/25 20:16:37 WARN TaskSetManager: Lost task 47.0 in stage 1.0 (TID 59, ip-172-31-28-175.ec2.internal): java.lang.OutOfMemoryError: Requested array size exceeds VM limit
        at java.util.Arrays.copyOf(Arrays.java:2271)
        at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:113)
        at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
        at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:140)
        at java.io.BufferedOutputStream.write(BufferedOutputStream.java:122)
        at com.ning.compress.lzf.ChunkEncoder.encodeAndWriteChunk(ChunkEncoder.java:264)
        at com.ning.compress.lzf.LZFOutputStream.writeCompressedBlock(LZFOutputStream.java:266)
        at com.ning.compress.lzf.LZFOutputStream.write(LZFOutputStream.java:124)
        at com.esotericsoftware.kryo.io.Output.flush(Output.java:155)
        at com.twitter.chill.TraversableSerializer$$anonfun$write$1.apply(Traversable.scala:31)
        at com.twitter.chill.TraversableSerializer$$anonfun$write$1.apply(Traversable.scala:27)
        at scala.collection.immutable.List.foreach(List.scala:318)
        at com.twitter.chill.TraversableSerializer.write(Traversable.scala:27)
        at com.twitter.chill.TraversableSerializer.write(Traversable.scala:21)
        at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:501)
        at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.write(FieldSerializer.java:564)
        at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:213)
        at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:501)
        at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.write(FieldSerializer.java:564)
        at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:213)
        at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:568)
        at com.twitter.chill.TraversableSerializer$$anonfun$write$1.apply(Traversable.scala:29)
        at com.twitter.chill.TraversableSerializer$$anonfun$write$1.apply(Traversable.scala:27)
        at scala.collection.immutable.List.foreach(List.scala:318)
        at com.twitter.chill.TraversableSerializer.write(Traversable.scala:27)
        at com.twitter.chill.TraversableSerializer.write(Traversable.scala:21)
        at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:501)
        at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.write(FieldSerializer.java:564)
        at com.esotericsoftware.kryo.serializers.FieldSerializer.write(FieldSerializer.java:213)
        at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:568)
        at org.apache.spark.serializer.KryoSerializationStream.writeObject(KryoSerializer.scala:124)
        at org.apache.spark.serializer.SerializationStream.writeAll(Serializer.scala:110)

我在驱动程序和执行程序上都有40GB的RAM。我尝试使用Kryo缓冲区大小/最大大小(从默认值一直增加到荒谬的值),但无济于事。

我做错了吗?这是一个知道问题吗?有解决方案吗?

编辑尝试了1.4.0同样的问题。

P.S。这只发生在集群上。在本地,我能让它成功运作。

总结

  1. 本地可以使用或不使用Kryo Serializer(虽然数据集较小),但使用1.3.1和1.4.0

  2. 在群集上,它使用默认的Java序列化程序,但在1.3.1和1.4.0上使用具有相同错误消息的Kryo序列化程序失败。

1 个答案:

答案 0 :(得分:0)

这个错误有点用词不当。这并不意味着你的机器没有足够的内存,这意味着Kryo试图用超过(2 ^ 31 -1)个元素创建一个字节数组。

这可能是因为你的Spark任务非常庞大。如果您已经在Scala中编写了Spark作业,则可能会意外地将额外的对象拉入作用域并使作业大小膨胀。这是什么意思?

  1. 当您通过Spark使用创建lambda函数时,Spark会查看lambda函数引用的所有对象
  2. 然后,
  3. Spark序列化它们并将它们与Task定义捆绑在一起。因此,如果要从lambda函数访问大型数据结构,外部类或全局变量,则可以轻松地将任务定义快速膨胀到大于(2 ^ 31 - 1)个字节的位置。
  4. 然后,当Kryo尝试使一个大于(2 ^ 31 - 1)的字节数组时,你所看到的OutOfMemoryException将被抛出。