我的 AWS Glue 提取、转换、加载 (ETL) 作业失败并出现错误“Container killed by YARN for exceeding memory limits”。
简短描述
以下是出现此错误的常见原因:
- 超过底层 Apache Spark 集群内存阈值的内存密集型操作。这些操作可能包括连接大型表或处理数据分布存在偏差的数据集。
- 消耗的内存超过分配给相应执行程序的内存的数据 FAT 分区。
- 无法拆分且会导致内存中分区过大的大型文件。
解决方法
要解决此错误,请完成下面的一个或多个解决方案。
升级 Worker 类型
由于 G.2x 具有更高的内存配置,请升级 Worker 类型。您可以将 Worker 类型从 G.1x 升级到以下 Worker 类型:
- G.2x
- G.4x
- G.8x
- G.12x
- G.16x
- R.1x
- R.2x
- R.4x
- R.8x
有关 Worker 类型规格的详细信息,请参阅定义 Spark 作业的作业属性和 AWS Glue 版本。
增加作业的执行程序
如果升级 Worker 类型后错误仍然存在,请增加作业执行程序的数量。对于每个执行程序,有一定数量的内核。该数字决定了执行程序可以处理的分区数量。Worker 类型定义数据处理单元 (DPU) 的 Spark 配置。
更新您的数据
为确保 AWS Glue 在进行随机操作(例如连接)之前均匀地使用执行程序,请验证您的数据是否并行。要在所有执行程序中重新分区数据,请在您的 ETL 作业中加入以下命令之一。
对于 DynamicFrame,请添加以下命令:
dynamicFrame.repartition(totalNumberOfExecutorCores)
对于 DataFrame,请添加以下命令:
dataframe.repartition(totalNumberOfExecutorCores)
使用作业书签
当您使用作业书签时,AWS Glue 作业仅处理新写入的文件。此配置可减少 AWS Glue 作业处理的文件数量并减少内存问题。书签存储上次运行的进程文件中的元数据。在接下来的运行中,作业会比较时间戳,然后决定是否再次处理这些文件。有关详细信息,请参阅使用作业书签跟踪已处理的数据。
使用 DynamicFrame 并行读取数据
当您连接到 JDBC 表时,默认情况下,Spark 仅打开一个并发连接。驱动程序尝试在单个 Spark 执行程序中一次性下载整个表。此下载过程可能需要更长时间,并可能导致执行程序出现内存不足 (OOM) 错误。请配置 JDBC 表的特定属性,以指示 AWS Glue 使用 DynamicFrame 并行读取数据。或者,您可以使用 Spark DataFrame 来实现从 JDBC 的并行读取。有关详细信息,请参阅 Spark 网站上的 JDBC to other databases(其他数据库的 JDBC)。
在 ETL 作业中使用高性能函数
对于您的 ETL 作业,不要使用用户定义的函数,尤其是当您将 Python 或 Scala 代码与 Spark 的函数和方法结合使用时。例如,不要使用 Spark df.count() 来验证 if/else 语句或 for 循环中的空 DataFrame。相反,使用性能更好的函数,例如 df.schema() 或 df.rdd.isEmpty()。
测试和优化 AWS Glue 作业
在生产环境中运行 AWS Glue 作业之前,请在交互式会话中测试 AWS Glue 作业并优化 ETL 代码。
如果上述解决方案选项均不起作用,请将输入数据拆分为区块或分区。然后,运行多个 AWS Glue ETL 作业,而不是运行单个大型作业。有关详细信息,请参阅具有有界执行的工作负载分区。
相关信息
调试 OOM 异常和作业异常
Best practices to scale Spark jobs and partition data with AWS Glue(使用 AWS Glue 扩展 Spark 作业和分区数据的最佳实践)
Optimize memory management in AWS Glue(优化 AWS Glue 中的内存管理)