火花内存限制超出问题

时间:2017-08-03 09:13:27

标签: scala hadoop apache-spark

我有一个在spark上运行的作业,并使用spark RDD在scala中编写。因为操作昂贵的组我得到这个错误:  Container killed by YARN for exceeding memory limits. 22.4 GB of 22 GB physical memory used. Consider boosting spark.yarn.executor.memoryOverhead。  我增加了内存,但我得到了同样的结果。我使用10台r4.xlarge机器。我尝试使用r4.2xlarge甚至r4.4xlarge但同样的错误。我测试的数据是5GB gzip压缩数据(几乎50个解压缩数据和近600万个记录)。

一些配置:

spark.executor.memory:20480M spark.driver.memory:21295M spark.yarn.executor.memoryOverhead:2g spark.executor.instances:10

代码如下:

val groupedEntitiesRDD = datasetRDD 
  .groupBy(_.entityId) 
  .map({ case (key, valueIterator) => key -> valueIterator.toList }) 
  .persist(StorageLevel.MEMORY_AND_DISK) 

val deduplicatedRDD = groupedEntitiesRDD 
  .flatMap({ case (_, entities) => deduplication(entities) }) 

def deduplication(entities: List[StreamObject[JsValue]]): List[StreamObject[JsValue]] = { 
  entities 
    .groupBy(_.deduplicationKey) 
    .values 
    .map(duplicates => duplicates.maxBy(_.processingTimestamp.toEpochSecond)) 
    .toList 
}

1 个答案:

答案 0 :(得分:2)

根据我的经验以及我在Spark 2.x的发行说明中所读到的内容,需要在堆内存(spark.yarn.executor.memoryOverhead)上分配比Spark 1.x更多的东西。

您只为MemoryOverhead和20GB内存分配了2G。如果你把它改成8G memoryOverhead和14GB执行程序内存,我相信你会得到更好的结果。

如果您仍然遇到内存问题(例如抛出实际的OOM),您将需要查看数据偏差。特别是groupBy操作经常会导致严重的数据偏差。

最后一件事,你写的是你使用RDDs - 我希望你的意思是DataFramesDataSetsRDDs groupBy的效果非常低(例如,请参阅this博客文章),因此,如果您在RDDs,则应使用reduceByKey。但基本上你应该使用DataFrames(或DataSet),其中groupBy确实是正确的方法。

编辑!

您在评论中询问如何将groupBy转换为reduceByKey。你可以这样做:

datasetRDD
  .map{case(entityID, streamObject) => (entityID, List(streamObject))}
  .reduceByKey(_++_)
  .flatMap{case(_, entities) => deduplication(entities)

您还没有指定这些实体的数据结构,但看起来您正在寻找一些最大值,实际上会丢弃不需要的数据。这应该构建到reduceByKey - 操作中,以便在减少时过滤掉不必要的数据。