在 Amazon EMR 上运行 Apache Spark - 大数据处理的集群设计与成本优化
介绍通过 EMR 构建 Spark 集群、EMR Serverless 的使用场景区分以及利用 Spot 实例进行成本优化的方法。
EMR 概述
EMR 是一项在托管集群上运行 Apache Spark、Hive、Presto、Flink 等 20 多种大数据框架的服务。集群由主节点、核心节点和任务节点组成,EMR 自动管理预置、配置和补丁更新。EMR Serverless 是 2022 年正式发布的模式,完全无需管理集群。只需提交 Spark 作业,所需资源即可自动预置。以 S3 为存储的「计算与存储分离」架构为标准做法,不依赖 HDFS 即可停止和重建集群,实现灵活的生命周期管理。
成本优化
EMR 的成本优化关键在于实例配置的设计。主节点和核心节点使用按需实例确保稳定性,任务节点使用 Spot 实例。由于任务节点不保存数据,Spot 中断时不存在数据丢失风险。通过实例队列指定多种实例类型,提高 Spot 的可用性。EMR Serverless 适用于间歇性作业,仅在作业执行期间计费。EMR on EC2 的费用包括 EC2 实例费用加上 EMR 管理费(约为 EC2 费用的 25%),因此对长时间运行的集群应用 Savings Plans 效果显著。
Spark 调优与数据格式
Spark 作业的性能很大程度上取决于分区数、Executor 配置和数据格式的选择。根据数据量调整 spark.sql.shuffle.partitions,将默认值 200 修改为合适的值。Parquet 格式采用列式存储,仅读取所需列,与 CSV 相比可大幅减少扫描量和处理时间。启用 Adaptive Query Execution (AQE) 后,系统会根据运行时统计信息自动优化 Shuffle 分区数和 Join 策略。使用 Delta Lake 或 Apache Iceberg 表格式,可在数据湖上实现 ACID 事务、时间旅行和 Schema 演进。Spark 3.x 以后的 Dynamic Partition Pruning (DPP) 可自动优化分区表的 Join,消除不必要的分区读取。 关于 EMR 的实践经验,也可以参考Amazon 上的相关书籍。
EMR 集群的成本管理
使用实例队列可以指定多种实例类型,最大化 Spot 的可用性。设置按需实例和 Spot 实例的混合比例,以按需实例确保基线容量,同时用 Spot 实例补充额外容量。EMR Serverless 无需集群管理,仅按作业执行时间计费,非常适合零散的批处理任务。对于长时间运行的集群,可应用 Savings Plans 获取承诺折扣。通过 CloudWatch 指标监控 YARN 的资源使用率,检测过大的集群规模并进行优化调整。启用 Managed Scaling 后,系统会根据 YARN 指标自动扩缩任务节点,仅在峰值时添加资源,空闲时缩减。
EMR on EC2、EMR Serverless、EMR on EKS 的选择
EMR 提供 3 种部署选项,根据工作负载特性进行选择。EMR on EC2 是传统的集群模式,适合需要精细自定义 Spark 配置、安装库或需要 HDFS 的工作负载。EMR Serverless 无需集群预置,适合日常批处理或零散 ETL 作业等「提交即等待」的工作负载。由于启动开销为数十秒,不适合需要低延迟的交互式查询。EMR on EKS 是在 Kubernetes 集群上运行 Spark 作业的选项,适合已运营 EKS 的团队统一基础设施或与其他容器工作负载共享资源。成本方面,EMR Serverless 对短时间作业的每 GB 单价往往低于 EC2,而长时间作业则通过 EC2 集群的 Spot + Savings Plans 组合实现更低成本。
设计陷阱与运维注意事项
在 EMR 上运行 Spark 时有几个常见问题。首先,小文件大量产生(Small File Problem)会增加元数据处理开销,并导致 S3 GET 请求费用膨胀。可通过 Spark 的 coalesce 或 repartition 控制输出文件数,或利用 Iceberg 的 compaction 功能定期合并小文件。其次,作为 Spot 实例中断的对策,启用 spark.speculation 对延迟任务进行投机执行,缩短中断任务的恢复时间。数据倾斜也是频发问题,数据集中在特定分区键时,Shuffle 阶段会出现内存不足或任务处理时间偏差。可通过 AQE 的 skew join 优化或 salting 手法(为键添加随机后缀以分散数据)来应对。最后,关于通过 EMR 的 EMRFS 访问 S3,S3 已于 2020 年 12 月切换为强一致性,历史上的一致性问题已不再存在。
总结
EMR 是一项以托管方式运行大数据框架的服务。通过 Adaptive Query Execution 自动优化 Spark 作业性能,利用 Parquet 格式和合理的分区设计提升查询效率。通过实例队列最大化 Spot 可用性,利用 EMR Serverless 提高零散批处理任务的成本效率。根据工作负载特性选择 3 种部署选项(EC2、Serverless、EKS),并通过设计预先规避 Small File Problem 和数据倾斜等运维陷阱,是实现稳定大规模数据处理的关键。