火花可扩展性:我做错了什么?

时间:2015-03-19 22:37:46

标签: apache-spark bigdata pyspark scalability distributed-computing

我正在使用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。

  1. 我做错了什么?
  2. 我尝试用saveAsTextFile替换collect(因为我实际上想在保存之前在python中做一些切片和切块),行为没有差别,同样的失败。这是预期的吗?
  3. 我曾经reduce(lambda x,y: x.union(y), [sqc.parquetFile(...)...])代替sc.union - 哪个更好?这有什么不同吗?
  4. 群集中有 25 个节点,其中 825GB 内存和 224 内核。

    调用是spark-submit --master yarn --num-executors 50 --executor-memory 5G

    单个RDD有大约140列并且包含一小时的数据,因此一周是168(= 7 * 24)个RDD的并集。

2 个答案:

答案 0 :(得分:2)

事实证明问题不在于火花,而在于纱线问题。 解决方案是用

运行spark
spark-submit --conf spark.yarn.executor.memoryOverhead=1000

(或修改纱线配置)。

答案 1 :(得分:2)

Spark在缩放时经常会遇到Out-Of-Memory错误。在这些情况下,应该由程序员进行微调。或者重新检查您的代码,以确保您不会做任何太多的事情,例如收集驱动程序中的所有,这很可能会超出 memoryOverhead 限制,无论你设置多大。

为了理解发生了什么,你应该意识到决定杀死一个超出内存限制的容器。当容器超出 memoryOverhead 限制时,就会发生这种情况。

在计划程序中,您可以检查事件时间轴以查看容器发生的情况。如果Yarn杀死了一个容器,它将显示为红色,当您将鼠标悬停/点击时,您将看到如下消息:

  

由于超出内存限制而被YARN杀死的容器。使用16.9 GB的16 GB物理内存。考虑提升spark.yarn.executor.memoryOverhead。

enter image description here

因此,在这种情况下,您要关注的是这些配置属性(值是 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容器相同,则它是驱动程序,否则是执行程序。

那没有解决问题,现在是什么?

您必须微调核心数量和您提供的堆内存。您看到将完成堆外内存中的大部分工作,因此您不希望为堆提供太多空间,因为这会浪费掉。你不想给予太少,因为垃圾收集器会有问题。回想一下,这些是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'