Apache Spark耗尽内存,分区数量较少

时间:2016-06-30 21:42:52

标签: apache-spark

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

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

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

3 个答案:

答案 0 :(得分:2)

Rockie的答案是正确的,但他不明白你的问题。

当您缓存RDD时,其所有分区都将保留(用storage level表示)-遵守 spark.memory.fraction spark.memory.storageFraction 属性。

此外, Spark可以在某些时候自动删除某些内存分区(或者您可以使用RDD.unpersist()手动对整个RDD进行此操作),具体方法根据{{3} }。

因此,当您拥有更多分区时,Spark在LRU中存储的分区会更少,这样它们就不会引起OOM(这可能也会产生负面影响,例如需要重新缓存分区)。

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

答案 1 :(得分:1)

大数据的解决方案是分区(分而治之)。由于并非所有数据都可以放入内存中,因此也无法在一台机器上处理。

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

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

<强> [编辑]

Spark使用名为Resilient Distributed DataSet(RDD)的革命概念。

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

Spark DAG

我在Youtube Spark Makes Big Data Sparking上进行了一次小型截屏视频演示。

答案 2 :(得分:0)

  

Spark的操作员将数据溢出到磁盘中(如果内存不适合),   使其可以在任何大小的数据上正常运行。”   生成OOM的分区

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

缺少分区会导致

  • 并发较少,
  • 增加涉及随机播放的转换的内存压力
  • 更容易出现数据偏斜。

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

  • 安排多个任务花费的时间过多

将数据存储在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毫秒内完成