问题描述
缓存的 RDD(总共 8 个)并不大,只有 30G 左右,但是,在 Hadoop UI 上,它表明 Spark 应用程序正在占用大量内存(没有活动作业运行),即1.4T,为什么这么多?
为什么即使没有活动作业在运行,它也会显示大约 100 个执行程序(此处为 vCore)?
此外,如果缓存的 RDD 存储在 100 个执行程序中,这些执行程序是否会保留下来,并且其他 Spark 应用程序不再可以使用它们来运行任务?换个说法:在 executor 中保留一点内存资源 (.cache
) 是否会阻止其他 Spark 应用利用它们的空闲计算资源?
是否有任何潜在的 Spark 配置 / zeppelin 配置会导致这种现象?
更新 1
检查 Spark conf (zeppelin) 后,似乎 spark.executor.memory=10G
有默认设置(默认由管理员配置),这可能是原因。
然而,这里有一个新问题:是否可以只保留每个执行器中缓存的 RDD 所需的内存并释放其余的内存,而不是始终保留初始设置的内存 spark.executor.memory=10G
?
Spark 配置
解决方法
也许您可以尝试在缓存之前将您的 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()
会导致改组,如果数据如此倾斜,如果执行程序没有足够的资源可能会导致其他问题 - 缓存不会帮助释放执行器上的内存,因为它不会重新分配数据
- 您能否在舞台上的“事件时间表”下看到“绿色条有多大?”通常这与数据分布相关,因此这是一种查看每个任务加载了多少数据(按比例)以及它们做了多少的方法。由于所有任务都分配了相同的内存,因此您可以以图形方式查看资源是否被浪费(如果大部分是小条,而很少有大条)。下图显示了资源浪费的示例
有多种方法可以为您的流程创建均匀分布的文件。我提到了一些可能性,但肯定还有更多: