主要观点:作为数据工程师遇到 Apache Spark 内存管理和内部处理的复杂挑战,一个 25GB 的数据集导致驱动程序内存溢出错误,文章讨论 Spark 内部处理复杂性和内存管理以构建弹性数据复制解决方案,深入探讨了 OOM 问题的原因(如生成的计划字符串过大、数据集内部表示等),提出了修复方法(关闭解释计划或优化实现,仅使用 DataFrame 操作计算净变化),并给出了 OOM 的快速经验法则(区分驱动程序和执行器的风险因素)。
关键信息:
- 场景:读取 25GB 的 DynamoDB 导出 JSON 数据,使用 Spark 进行处理,执行简单的
isEmpty()操作时出现 OOM 错误。 - 原因:Spark 为日志、UI 等目的生成计划字符串表示,由于数据集内部表示和 Spark 遍历生成计划,导致计划字符串过大,消耗大量内存。
- 修复方法:关闭解释计划(目前 Spark 无此功能)或优化实现,仅使用 DataFrame 操作计算净变化,本地测试显示内存消耗显著降低。
- OOM 经验法则:区分驱动程序和执行器的内存风险因素,如驱动程序的
collect等操作和执行器的shuffle等操作。
重要细节:
- 集群配置:9 台机器的 Glue Spark 集群,每台机器 32vCPU 和 128GB 内存。
- 代码细节:展示了导致 OOM 的代码片段,包括从读取数据到计算净变化的过程,以及优化后的仅使用 DataFrame 操作的代码。
- 堆栈跟踪:详细的 OOM 堆栈跟踪,显示 Spark 在执行过程中调用
explainString方法生成计划字符串。 - 内存相关属性:Spark 中控制计划生成的
maxToStringFields或maxPlanStringLength属性,仅影响格式化或截断输出,不控制遍历本身。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。