【问题标题】:Apache Spark running out of memory with smaller amount of partitionsApache Spark 内存不足,分区数量较少
【发布时间】:2016-06-30 21:42:52
【问题描述】:

我有一个 Spark 应用程序,内存不断不足,集群有两个节点,内存大约 30G,输入数据大小约为几百 GB。

该应用程序是一个 Spark SQL 作业,它从 HDFS 读取数据并创建一个表并缓存它,然后执行一些 Spark SQL 查询并将结果写回 HDFS。

最初我将数据分成 64 个分区并得到 OOM,然后我能够通过使用 1024 个分区来解决内存问题。但是为什么使用更多的分区可以帮助我解决 OOM 问题呢?

【问题讨论】:

    标签: apache-spark


    【解决方案1】:

    大数据的解决方案是分区(分而治之)。由于不是所有的数据都可以放入内存,也不能在单机上处理。

    每个分区都可以在相对较短的时间内放入内存并处理(映射)。在为每个分区处理数据之后。它需要合并(减少)。这是传统map reduce

    将数据拆分到更多分区意味着每个分区越来越小。

    [编辑]

    Spark 使用称为弹性分布式数据集 (RDD) 的革命概念。

    • 有两种类型的操作,转换和动作
    • 转换是从一个 RDD 映射到另一个。它是懒惰的评估。这些 RDD 可能会被视为我们不想得到的中间结果。
    • 当您真正想要获取数据时使用操作。那些 RDD/数据可以被视为我们想要的,比如 take top failure。
    • Spark 会在执行前分析所有操作并创建 DAG(有向无环图)。
    • 触发操作时,Spark 从源 RDD 开始计算。那就算了吧。


    (来源:cloudera.com

    我为 Youtube Spark Makes Big Data Sparking 上的演示制作了一个小截屏视频。

    【讨论】:

    • 我同意每个分区的大小更小,但是由于我正在缓存 RDD(应该在帖子中提到这一点),这些分区应该仍然在内存中,对吗?所以不管分区多少,内存中数据的大小应该是一样的
    【解决方案2】:

    Spark 的操作符在内存无法容纳的情况下将数据溢出到磁盘, 允许它在任何大小的数据上运行良好”。大问题 分区产生OOM

    分区决定并行度。 Apache Spark 文档说,分区大小应该至少等于集群中的核心数。

    更少的分区导致

    • 更少的并发,
    • 为涉及 shuffle 的转换增加内存压力
    • 更容易受到数据倾斜的影响。

    许多分区也可能产生负面影响

    • 安排多个任务花费了太多时间

    将您的数据存储在 HDFS 上,将根据您的 HDFS 配置将其分区为 64 MB 或 128 MB 块使用 spark 读取 HDFS 文件时,DataFrame 分区的数量 df.rdd.getNumPartitions取决于以下属性

    • spark.default.parallelism(应用程序可用的内核)
    • spark.sql.files.maxPartitionBytes(默认 128MB)
    • spark.sql.files.openCostInBytes(默认 4MB)

    链接:

    在 Spark 峰会期间,Aaron Davidson 提供了一些关于分区调优的技巧。他还定义了合理的分区数恢复到3点以下:

    • 通常在 100 到 10000 个分区之间(注意:以下两点更可靠,因为此处的“通常”取决于数据集和集群的大小)
    • 下限 = 至少 2* 集群中的核心数
    • 上限 = 任务必须在 100 毫秒内完成

    【讨论】:

      【解决方案3】:

      Rockie 的回答是对的,但他没有明白你问题的重点。

      当你缓存一个 RDD 时,他的所有分区都会被持久化(以storage level 表示)——尊重 spark.memory.fractionspark.memory.storageFraction属性。

      除此之外,根据documentation,在某个时刻Spark 可以自动删除一些内存分区(或者您可以使用 RDD.unpersist() 手动为整个 RDD 执行此操作)。

      因此,由于您有更多分区,Spark 在 LRU 中存储的分区更少,因此它们不会导致 OOM(这也可能产生负面影响,例如需要重新缓存分区)。

      另一个重要的一点是,当您使用 X 个分区将结果写回 HDFS 时,您的所有数据都有 X 个任务 - 将所有数据大小除以 X,这就是内存对于每个任务,在每个(虚拟)核心上执行。所以,不难看出 X = 64 会导致 OOM,但 X = 1024 不会。

      【讨论】:

        猜你喜欢
        • 2019-01-03
        • 1970-01-01
        • 2014-05-03
        • 1970-01-01
        • 2019-05-08
        • 2022-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多