apache-spark - 优化 Spark 资源以避免内存和空间使用
问题描述
我有一个大约 190GB 的数据集,它被分成 1000 个分区。
我的 EMR 集群最多允许 10 个r5a.2xlarge
TASK 节点和 2 个 CORE 节点。每个节点有 64GB 内存和 128GB EBS 存储。
在我的 spark 作业执行中,我已将其设置为使用executor-cores 5
, driver cores 5
, executor-memory 40g
, driver-memory 50g
, spark.yarn.executor.memoryOverhead=10g
, spark.sql.shuffle.partitions=500
,spark.dynamicAllocation.enabled=true
但我的工作一直因错误而失败,例如
spark.shuffle.MetadataFetchFailedException
spark.shuffle.FetchFailedException
java.io.IOException: No space left on device
Container Lost
etc...
我在网上找到的很多这类问题的答案都说会增加内存开销。我做到了,从 2G 到 10G。executor memory
我的一共memoryOverhead
是50G。40G 分配给执行者,10G 分配给开销。但我认为我已经达到了极限,因为我无法超过 56。
我认为我已尽一切可能优化我的 Spark 工作:
- 增加分区
- 增加 spark.sql.shuffle.partitions
- 增加执行器和开销内存
但我的工作仍然失败。还有什么我可以尝试的吗?我应该更多地增加我的开销,以便我的执行程序内存/开销内存为 50/50?我在 ganglia 工作的内存配置文件如下所示:
(急剧下降是当集群由于它们死亡而刷新所有执行程序节点时)
任何见解将不胜感激
谢谢你
编辑:[解决方案]
Debuggerrr
由于基于他在回答中的建议,我将在我的帖子中附加了解决我的问题的确切解决方案。
- 我有一个大型数据框,在对其他数据框进行多次计算后,我正在重新使用它。通过使用该
persist()
方法(由 Debuggerrr 建议),我能够将其保存到 MEMORY 和 DISC 并简单地调用它而无需 GC 清理它的一部分。 - 我还按照他的回答中提到的最佳实践博客 Debuggerrr 计算了正确的执行程序内存、执行程序数量等。但我没有做的是 disable
spark.dynamicAllocation.enabled
。该博客指出,如果我们手动计算资源,最好将该属性设置为 false,因为如果您的计算与它不一致,spark 往往会错误分配资源。一旦我将其设置为 false,并设置了正确的 executor 和 spark 属性,它就像一个魅力!
[编辑 2]:专门为我的工作工作 的参数是:
--executor-cores 5 --driver-cores 5 --executor-memory 44g --driver-memory 44g --num-executors 9 --conf spark.default.parallelism=100 --conf spark.sql.shuffle.partitions=300 --conf spark.yarn.executor.memoryOverhead=11g --conf spark.shuffle.io.retryWait=180s --conf spark.network.timeout=800s --conf spark.serializer=org.apache.spark.serializer.KryoSerializer --conf spark.dynamicAllocation.enabled=false
解决方案
您可以尝试以下任一步骤:
Memory overhead
应该是10%
Executor 内存或328 MB
. 不要将其增加到任何值。- 删除驱动程序核心。
- 如果您有 10 个节点,则指定
number of executors
. 您必须以为 YARN 和后台进程留出一些空间的方式计算它。此外,您可以尝试增加 1 或 2 个内核。 - 在一个模式下运行它
cluster
,无论您分配给执行器的数量是多少,都为其添加 +1,因为在集群模式下 1 个执行器将被视为驱动程序执行器。 - 此外,最后一件事就是您为提交/处理该 190GB 文件而编写的代码。浏览您的代码并找到优化它的方法。寻找收集方法,或不必要地使用连接、合并/重新分区。如果不需要的话,找一些替代品。
- 对您在代码中经常使用的数据帧使用持久(仅限内存和磁盘)选项。
- 此外,我尝试的最后一件事是手动执行这些步骤
spark-shell on EMR
,您将知道代码的哪一部分需要花费很多时间来运行。
您也可以参考这个官方博客以获取一些提示。
推荐阅读
- docker - 一个容器如何生活在两个网络中可以找到每个网络的同名容器
- aws-lambda - Secrets Manage:无法轮换密钥,无法调用指定的 Lambda 函数
- jquery - 将文本附加到文本框输入
- c# - 在没有网络挂钩的 asp.net 中具有 3D 安全的 Stripe 支付网关
- python - 如何自动更新 tkinter 中的输入变量?
- html - 如何使用相对定位将两个容器彼此相邻放置
- javascript - 路由更改 hls.js React.js 时未捕获的 DOMException
- r - 基于值的 IF ELSE 生成器
- java - 在我的自定义注释中使用 Spring 属性 @Value
- java - 为什么 onStart() 方法在我的 android 项目中的 onCreate 之前运行?