为什么缓存小型 Spark RDD 需要在 Yarn 中分配大量内存?

问题描述

缓存的 RDD(总共 8 个)并不大,只有 30G 左右,但是,在 Hadoop UI 上,它表明 Spark 应用程序正在占用大量内存(没有活动作业运行),即1.4T,为什么这么多?

enter image description here

enter image description here

为什么即使没有活动作业在运行,它也会显示大约 100 个执行程序(此处为 vCore)?

此外,如果缓存的 RDD 存储在 100 个执行程序中,这些执行程序是否会保留下来,并且其他 Spark 应用程序不再可以使用它们来运行任务?换个说法:在 executor 中保留一点内存资源 (.cache) 是否会阻止其他 Spark 应用利用它们的空闲计算资源?

是否有任何潜在的 Spark 配置 / zeppelin 配置会导致这种现象?


更新 1

检查 Spark conf (zeppelin) 后,似乎 spark.executor.memory=10G认设置(认由管理员配置),这可能是原因。

然而,这里有一个新问题:是否可以只保留每个执行器中缓存的 RDD 所需的内存并释放其余的内存,而不是始终保留初始设置的内存 spark.executor.memory=10G

Spark 配置

enter image description here

解决方法

也许您可以尝试在缓存之前将您的 RDD repartition(n) 分配到更少的 n < 100 分区。大约 30GB 的 RDD 可能适合十个 10GB 执行器的存储内存。可以在 here 中找到有关 Spark 内存管理的很好的概述。这样,只有那些持有缓存块的执行器才会被“固定”到您的应用程序,而其余的可以在 spark.dynamicAllocation.executorIdleTimeout(默认 60 秒)之后由 YARN 通过 Spark 动态分配回收。

问:是否可以只保留每个执行器中缓存的 RDD 所需的内存并释放其余的内存,而不是始终保留初始设置的内存 spark.executor.memory=10G?

当 Spark 使用 YARN 作为其执行引擎时,YARN 会为所有执行程序分配指定(按应用程序)大小的容器——至少 spark.executor.memory+spark.executor.memoryOverhead,但在 pyspark 的情况下可能更大。 Spark 在容器中实际使用了多少内存变得无关紧要,因为分配给容器的资源将被视为禁止其他 YARN 应用程序使用。

,

Spark 假设您的数据平均分布在所有执行程序和任务上。这就是您为每个任务设置内存的原因。所以为了让 Spark 消耗更少的内存,你的数据必须均匀分布:

  • 如果您从 Parquet 文件或 CSV 中读取数据,请确保它们具有相似的大小。运行 repartition() 会导致改组,如果数据如此倾斜,如果执行程序没有足够的资源可能会导致其他问题
  • 缓存不会帮助释放执行器上的内存,因为它不会重新分配数据
  • 您能否在舞台上的“事件时间表”下看到“绿色条有多大?”通常这与数据分布相关,因此这是一种查看每个任务加载了多少数据(按比例)以及它们做了​​多少的方法。由于所有任务都分配了相同的内存,因此您可以以图形方式查看资源是否被浪费(如果大部分是小条,而很少有大条)。下图显示了资源浪费的示例

enter image description here

有多种方法可以为您的流程创建均匀分布的文件。我提到了一些可能性,但肯定还有更多:

  • 使用 Hive 和 DISTRIBUTE BY 子句:您需要使用一个平衡的字段,以便创建与预期一样多的文件(并具有适当的大小)
  • 如果创建这些文件的进程是从数据库读取的 Spark 进程,请尝试创建与您需要的文件一样多的连接,并使用适当的字段来填充 Spark 分区。这是实现的,如 herehere 与 partitionColumn、lowerBound、upperBound 和 numPartitions 属性的解释
  • 重新分区可能有效,但看看在您的过程中或在生成您正在读取的文件的前一个过程中合并是否也有意义

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...