我的 AWS Glue 提取、转换、加载(ETL)任务失败,并且显示错误“Container killed by YARN for exceeding memory limits(由于超出内存限制,容器被 YARN 终止)”。
简短描述
造成此错误的最常见原因如下:
- 内存密集型操作,例如连接大型表或处理特定列值分布偏差的数据集,超过了基础 Spark 集群的内存阈值
- 数据 FAT 分区的内存耗用量超过分配给相应执行程序的内存
- 无法拆分的大文件导致内存中分区较大
解决方法
使用以下一种或多种解决方案以解决此错误:
| |
---|
AWS Glue 版本 1.0 和 2.0 | |
标准 | spark.executor.memory: 5g spark.driver.memory: 5g spark.executor.cores: 4 |
G.1x | spark.executor.memory: 10g spark.driver.memory: 10g spark.executor.cores: 8 |
G.2x | spark.executor.memory: 20g spark.driver.memory: 20g spark.executor.cores: 16 |
AWS Glue 3.0 版 | |
标准 | spark.executor.memory: 5g spark.driver.memory: 5g spark.executor.cores: 4 |
G.1x | spark.executor.memory: 10g spark.driver.memory: 10g spark.executor.cores: 4 |
G.2x | spark.executor.memory: 20g spark.driver.memory: 20g spark.executor.cores: 8 |
- 如果升级工作线程类型后错误仍然存在,则增加任务的执行程序数量。每个执行程序都有一定数量的内核。此数字决定了执行程序可以处理的分区数。数据处理单元 (DPU) 的 Spark 配置是根据工作线程类型定义的。
- 确保数据已正确得到并行处理,以便在任何随机操作 (例如连接) 之前均匀使用执行程序。您可以在所有执行程序之间重新分区数据。可以在 ETL 任务中分别包含以下适用于 AWS Glue DynamicFrame 和 Spark DataFrame 的命令来实现这一点。
dynamicFrame.repartition(totalNumberOfExecutorCores)
dataframe.repartition(totalNumberOfExecutorCores)
- 使用任务书签仅允许 AWS Glue 任务处理新写入的文件。这可以减少 AWS Glue 任务处理的文件量,并缓解内存问题。书签存储有关上次运行中所处理文件的元数据。在随后的运行中,任务会比较时间戳,然后决定是否再次处理这些文件。有关详细信息,请参阅使用任务书签跟踪处理的数据。
- 在连接到 JDBC 表时,默认情况下,Spark 仅打开一个并发连接。驱动程序尝试在单个 Spark 执行程序中同时下载整个表。这可能需要更长的时间,甚至会导致执行程序的内存不足错误。相反,您可以设置 JDBC 表的特定属性,以指示 AWS Glue 通过 DynamicFrame 并行读取数据。有关更多信息,请参阅并行读取 JDBC 表。或者,您可以通过 Spark DataFrame 从 JDBC 实现并行读取。有关更多信息,请参阅 Spark DataFrame 并行从 JDBC 读取,并查看属性,例如 partitionColumn、lowerBound、upperBound 和 numPartitions。
- 避免在 ETL 任务中使用用户定义的函数,尤其是在将 Python/Scala 代码与 Spark 的函数和方法结合使用时。例如,避免使用 Spark 的 df.count() 来验证 if/else 语句或 for 循环中的空 DataFrames。相反,请使用更优性能的函数,例如 df.schema () 或 df.rdd.isEmpty()。
- 在开发端点上测试 AWS Glue 任务,并相应地优化 ETL 代码。
- 如果上述解决方案选项都不起作用,请将输入数据拆分为块或分区。然后,运行多个 AWS Glue ETL 任务,而不是运行一个大型任务。有关更多信息,请参阅有限执行的工作负载分区。
相关信息
调试 OOM 异常和任务异常
使用 AWS Glue 扩展 Apache Spark 任务和对数据进行分区的最佳实践
Optimize memory management in AWS Glue