我们正在使用在Spark runner上执行的Apache Beam。我们的案例如下。这两个用例都会导致OutofMemory错误。
1)加入 - 使用Apache Beam的2个大表 - 一个大小为120GB的表,另一个为60GB。当在GroupCombineFunctions.java内部调用groupByKeyOnly()时,这会导致OutofMemory错误。
2)GroupByKey - 我们基于如下的键对数据集进行分组。 PCollection>> costBasisRecords = masterDataResult.apply(GroupByKey.create());
此GroupbyKey操作也会导致OutOfmemory错误。
请您给我们一些建议,以便我们取得成果。
在线,我们看到 reduceByKey 方法 - 您能否指导我们如何为Spark跑步者实现该功能。
错误讯息:
java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.lang.reflect.Array.newInstance(Array.java:75)
at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1897)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1529)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:422)
at org.apache.spark.serializer.JavaDeserializationStream.readObject(JavaSerializer.scala:76)
at org.apache.spark.serializer.DeserializationStream.readValue(Serializer.scala:171)
at org.apache.spark.serializer.DeserializationStream$$anon$2.getNext(Serializer.scala:201)
at org.apache.spark.serializer.DeserializationStream$$anon$2.getNext(Serializer.scala:198)
at org.apache.spark.util.NextIterator.hasNext(NextIterator.scala:73)
at scala.collection.Iterator$$anon$13.hasNext(Iterator.scala:371)
at scala.collection.Iterator$$anon$11.hasNext(Iterator.scala:327)
at org.apache.spark.util.CompletionIterator.hasNext(CompletionIterator.scala:32)
at org.apache.spark.InterruptibleIterator.hasNext(InterruptibleIterator.scala:39)
at org.apache.spark.util.collection.ExternalAppendOnlyMap.insertAll(ExternalAppendOnlyMap.scala:152)
at org.apache.spark.Aggregator.combineValuesByKey(Aggregator.scala:45)
at org.apache.spark.shuffle.BlockStoreShuffleReader.read(BlockStoreShuffleReader.scala:89)
at org.apache.spark.rdd.ShuffledRDD.compute(ShuffledRDD.scala:98)
at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:306)
at org.apache.spark.rdd.RDD.iterator(RDD.scala:270)
at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:306)
at org.apache.spark.rdd.RDD.iterator(RDD.scala:270)
at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:306)
at org.apache.spark.rdd.RDD.iterator(RDD.scala:270)
at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:306)
at org.apache.spark.rdd.RDD.iterator(RDD.scala:270)
at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:306)
at org.apache.spark.rdd.RDD.iterator(RDD.scala:270)
at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
答案 0 :(得分:0)
reduceByKey
与Apache Beam中的Combine.perKey
类似,请参阅Programming Guide示例。
请注意,reduceByKey
和Combine.perKey
只有在每个密钥减少时才有效,否则您只会遇到相同的内存不足问题。例如,将每个键的所有整数组合到一个列表中不会减少内存使用量,但会对每个键的整数求和。
答案 1 :(得分:0)
如果可能,我肯定会建议使用Combine.perKey
作为Lukasz建议。
如果您无法执行此操作或仍遇到OOM,请尝试通过增加分区数来减小分区大小。您可以通过手动设置spark.default.parallelism
配置来增加shuffle分区的数量。这是explicitly used来确定groupByKeyOnly
shuffle的分区方案。
通过手动构建的SparkContextOptions
看起来探测配置的方式。有一个test case,显示了如何执行此操作。请注意,这需要您的管道程序直接链接到Spark。例如:
SparkConf conf = new SparkConf().set("spark.default.parallelism", parallelism);
JavaSparkContext jsc = new JavaSparkContext(conf);
SparkContextOptions options = PipelineOptionsFactory.as(SparkContextOptions.class);
options.setUsesProvidedSparkContext(true);
options.setProvidedSparkContext(jsc);
Pipeline p = Pipeline.create(options);
// ...
注意:Spark有自己的限制,即给定键的所有分组值必须适合处理该键的机器的内存。如果这不适用于您的数据集(即,您有非常强的密钥偏斜),那么您需要来组合而不是按组分组。