我正在使用spark处理数据,它可以处理一天的数据(40G),但是在一周的数据中 OOM 会失败:
import pyspark
import datetime
import operator
sc = pyspark.SparkContext()
sqc = pyspark.sql.SQLContext(sc)
sc.union([sqc.parquetFile(hour.strftime('.....'))
.map(lambda row:(row.id, row.foo))
for hour in myrange(beg,end,datetime.timedelta(0,3600))]) \
.reduceByKey(operator.add).saveAsTextFile("myoutput")
不同ID的数量小于10k。
每个ID都很小int
。
由于太多执行程序因OOM而失败,因此作业失败。
当作业成功时(在小输入上),"myoutput"
大约是100k。
saveAsTextFile
替换collect
(因为我实际上想在保存之前在python中做一些切片和切块),行为没有差别,同样的失败。这是预期的吗?reduce(lambda x,y: x.union(y), [sqc.parquetFile(...)...])
代替sc.union
- 哪个更好?这有什么不同吗?群集中有 25 个节点,其中 825GB 内存和 224 内核。
调用是spark-submit --master yarn --num-executors 50 --executor-memory 5G
。
单个RDD有大约140列并且包含一小时的数据,因此一周是168(= 7 * 24)个RDD的并集。
答案 0 :(得分:2)
事实证明问题不在于火花,而在于纱线问题。 解决方案是用
运行sparkspark-submit --conf spark.yarn.executor.memoryOverhead=1000
(或修改纱线配置)。
答案 1 :(得分:2)
Spark在缩放时经常会遇到Out-Of-Memory错误。在这些情况下,应该由程序员进行微调。或者重新检查您的代码,以确保您不会做任何太多的事情,例如收集驱动程序中的所有bigdata,这很可能会超出 memoryOverhead 限制,无论你设置多大。
为了理解发生了什么,你应该意识到yarn决定杀死一个超出内存限制的容器。当容器超出 memoryOverhead 限制时,就会发生这种情况。
在计划程序中,您可以检查事件时间轴以查看容器发生的情况。如果Yarn杀死了一个容器,它将显示为红色,当您将鼠标悬停/点击时,您将看到如下消息:
由于超出内存限制而被YARN杀死的容器。使用16.9 GB的16 GB物理内存。考虑提升spark.yarn.executor.memoryOverhead。
因此,在这种情况下,您要关注的是这些配置属性(值是 my 集群中的示例):
# More executor memory overhead
spark.yarn.executor.memoryOverhead 4096
# More driver memory overhead
spark.yarn.driver.memoryOverhead 8192
# Max on my nodes
#spark.executor.cores 8
#spark.executor.memory 12G
# For the executors
spark.executor.cores 6
spark.executor.memory 8G
# For the driver
spark.driver.cores 6
spark.driver.memory 8G
首先要做的是增加memoryOverhead
。
在驱动程序或执行程序中?
当您从UI概述群集时,可以单击“尝试ID”并检查诊断信息,其中应提及已杀死容器的ID。如果它与 AM容器相同,则它是驱动程序,否则是执行程序。
那没有解决问题,现在是什么?
您必须微调核心数量和您提供的堆内存。您看到pyspark将完成堆外内存中的大部分工作,因此您不希望为堆提供太多空间,因为这会浪费掉。你不想给予太少,因为垃圾收集器会有问题。回想一下,这些是JVM。
正如here所述,一个worker可以托管多个执行器,因此使用的内核数量会影响每个执行器的内存量,因此减少#cores可能有所帮助。
我用memoryOverhead issue in Spark和Spark - Container exited with a non-zero exit code 143更详细地写了它,大部分是我不会忘记的!另一个我未尝试过的选项是spark.default.parallelism或/和spark.storage.memoryFraction
,根据我的经验,它没有帮助。
您可以将配置标志传递为提到的sds,或者像这样:
spark-submit --properties-file my_properties
其中" my_properties"就像我上面列出的属性一样。
对于非数值,您可以这样做:
spark-submit --conf spark.executor.memory='4G'