Scala 火花存储器超出限制问题
我有一个在spark上运行的作业,它是使用spark RDD在scala im中编写的。由于group by操作成本高昂,我遇到以下错误:Scala 火花存储器超出限制问题,scala,hadoop,apache-spark,Scala,Hadoop,Apache Spark,我有一个在spark上运行的作业,它是使用spark RDD在scala im中编写的。由于group by操作成本高昂,我遇到以下错误: 容器因超过内存限制而被纱线杀死。使用22.4 GB的22 GB物理内存。考虑提升火花。纱线。执行器。内存开销< /代码>。 我增加了记忆,但我得到了同样的结果。我使用10台r4.xlarge机器。我尝试使用r4.2xlarge,甚至r4.4xlagle,但也有相同的错误。该数据在is 5GB Gzip数据(近50个解压缩数据和近600万条记录)上进行im测试
容器因超过内存限制而被纱线杀死。使用22.4 GB的22 GB物理内存。考虑提升火花。纱线。执行器。内存开销< /代码>。
我增加了记忆,但我得到了同样的结果。我使用10台r4.xlarge机器。我尝试使用r4.2xlarge,甚至r4.4xlagle,但也有相同的错误。该数据在is 5GB Gzip数据(近50个解压缩数据和近600万条记录)上进行im测试
一些配置:
spark.executor.memory
:20480M
spark.driver.memory
:21295M
火花、纱线、执行器、记忆头
: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
}
datasetRDD
.map{case(entityID, streamObject) => (entityID, List(streamObject))}
.reduceByKey(_++_)
.flatMap{case(_, entities) => deduplication(entities)
根据我的经验和我在Spark 2.x发行说明中读到的内容,需要分配比Spark 1.x多得多的堆外内存(Spark.Thread.executor.memoryOverhead
)
您只将2G分配给了内存溢出和20GB内存。我相信,如果您将其更改为8G memoryOverhead和14GB executor memory,您将获得更好的结果
如果您仍然遇到内存问题(如实际抛出的oom),则需要查看数据倾斜。尤其是groupBy
操作经常会导致严重的数据倾斜
最后一件事,您编写了使用rdd
——我希望您指的是DataFrames
或dataset
RDDs
在groupBy
中的性能非常低(请参见博客文章了解原因),因此如果您使用RDDs
您应该改用reduceByKey
。但实际上,您应该使用数据帧(或数据集),而groupBy
确实是正确的选择
编辑强>
您在评论中询问了如何将groupBy
转换为reduceByKey
。您可以这样做:
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
}
datasetRDD
.map{case(entityID, streamObject) => (entityID, List(streamObject))}
.reduceByKey(_++_)
.flatMap{case(_, entities) => deduplication(entities)
您尚未指定这些实体的数据结构,但看起来您正在寻找一些最大值,实际上是在丢弃不需要的数据。这应该内置到reduceByKey
-操作中,以便在减少时过滤掉不必要的数据。根据我的经验以及我在Spark 2.x发行说明中所读到的内容,需要分配比Spark 1.x多得多的堆外内存(Spark.Thread.executor.memoryOverhead
)
您只将2G分配给了内存溢出和20GB内存。我相信,如果您将其更改为8G memoryOverhead和14GB executor memory,您将获得更好的结果
如果您仍然遇到内存问题(如实际抛出的oom),则需要查看数据倾斜。尤其是groupBy
操作经常会导致严重的数据倾斜
最后一件事,您编写了使用rdd
——我希望您指的是DataFrames
或dataset
RDDs
在groupBy
中的性能非常低(请参见博客文章了解原因),因此如果您使用RDDs
您应该改用reduceByKey
。但实际上,您应该使用数据帧(或数据集),而groupBy
确实是正确的选择
编辑强>
您在评论中询问了如何将groupBy
转换为reduceByKey
。您可以这样做:
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
}
datasetRDD
.map{case(entityID, streamObject) => (entityID, List(streamObject))}
.reduceByKey(_++_)
.flatMap{case(_, entities) => deduplication(entities)
您尚未指定这些实体的数据结构,但看起来您正在寻找一些最大值,实际上是在丢弃不需要的数据。这应该内置在reduceByKey
-操作中,以便在减少时过滤掉不必要的数据。您使用的Spark版本是什么?Spark版本:2.1.1以及您是如何配置内存设置的?每个执行器上有多少内存、多少开销和多少执行器?@Glenniehellesindholt我将这些信息添加到问题中,询问您使用的是什么版本的Spark?Spark版本:2.1.1以及您如何配置内存设置?每个执行器上有多少内存,多少开销和多少执行器?@GlennieHellesSindholt我将信息添加到了问题中,谢谢。我将尝试更改executor内存和内存开销的配置,然后再次测试。关于选择RDD,本文说它是许多聚合操作(包括groupBy)中最快的,是的,但是如果您阅读RDD上“groupBy”操作的代码,您会注意到它们使用reduceByKey
;-)我的意思是阅读你参考的文章中的代码-他们使用reduceByKey
而不是groupBy
。好的,谢谢。您是否有将group by与数据帧一起使用的示例。或者如何使用reduce代替数据帧。我有一个重复数据消除应用程序,在这种情况下,不能使用reduce代替groupByreduceByKey
是RDDs
上的一个函数,它始终可以代替groupBy
-函数使用。如果您发布代码,我可以帮助您将其转换为使用reduceByKey
而不是groupBy
谢谢。我将尝试更改executor内存和内存开销的配置,然后再次测试。关于选择RDD,本文说它是许多聚合操作(包括groupBy)中最快的,是的,但是如果您阅读RDD上“groupBy”操作的代码,您会注意到它们使用reduceByKey
;-)我的意思是阅读你参考的文章中的代码-他们使用reduceByKey
而不是groupBy
。好的,谢谢。您是否有将group by与数据帧一起使用的示例。或者如何使用reduce代替数据帧。我有一个重复数据消除应用程序,在这种情况下,reduce不能代替groupBy使用reduceByKey
是RDDs
上的一个函数,它始终可以代替groupBy使用