Spark 批处理调优这点事:资源怎么要、Shuffle 怎么省、序列化怎么选?我用这些年踩过的坑告诉你

简介: Spark 批处理调优这点事:资源怎么要、Shuffle 怎么省、序列化怎么选?我用这些年踩过的坑告诉你

Spark 批处理调优这点事:资源怎么要、Shuffle 怎么省、序列化怎么选?我用这些年踩过的坑告诉你

大家好,这里是大数据圈里“被 Yarn 吊着打过、和 Spark 吵过架”的 Echo_Wish。
今天咱们来聊聊 Spark 批处理作业的调优。别听到“调优”两个字就觉得高大上,它其实本质就是三句话:

资源别瞎要、Shuffle 别乱搞、序列化别拖后腿。

你能把这三件事整明白,70% 的性能问题都会给你让路。剩下 30% 基本靠缘分和运维同事心情。

这篇文章,我想和你聊点真东西:你能立刻用、立刻见效、能救你半夜线上跑不动作业的那种优化技巧。


一、资源调优:要得对比要得多更重要

Spark 作业的资源问题,大部分不是资源少,而是资源分配的方式完全不对。

1. Executor 数量和 CPU 核心到底怎么配?

这里给你一个我自己线上测试无数次得出的“黄金思路”:

  • Executor 内核数别超过 5~6 个
    因为再多 GC 压力大、上下文切换更大、反而越跑越慢。

  • Executor 数量比核心数量更重要
    小 Executor + 多 Executor 往往比 大 Executor + 少 Executor 更稳。

例如,你的集群有 50 核想全用上,不要这样配:

# 典型的错误配置:又大又笨
--executor-cores 10
--num-executors 5

应该这样:

# 典型的性能更优配置:小而精,数量多
--executor-cores 5
--num-executors 10

为什么?
因为大 Executor 会导致:

  • GC 时间飙升
  • Shuffle 文件争抢
  • Task 并发不均衡

而小 Executor 则让资源调度更灵活、稳定性更高。


2. Executor 内存不是越大越好

很多朋友喜欢直接开 20G、30G 内存的 Executor,我只能说:
你这是把自己的作业推进了 GC 炼狱

合理内存一般在 6~12G 之间,特别是 ETL 型作业。

万一你非要调大?那至少要打开:

--conf spark.memory.fraction=0.6
--conf spark.memory.storageFraction=0.3

否则别怪 Spark 动不动 OOM。


二、Shuffle 调优:能绕开就绕开,绕不开就优化

Shuffle 是 Spark 性能最大的杀手,没有之一。
凡是经过 Shuffle 的地方,都会:

  • 打断 pipeline
  • 写磁盘、读磁盘
  • 网络传输
  • 排序 & 聚合

你要做的不是“优化 Shuffle”,而是“减少 Shuffle”!

1. 尽量避免两个最致命的操作:groupByKeyjoin

groupByKey 是性能灾难,因为它会把 key 相同的所有 value 拉到同一个 Executor。

举个例子:

// 千万别这么写!这是 shuffle 地狱!
rdd.groupByKey()

正确写法应该使用 reduceByKey / aggregateByKey

// reduceByKey 会在 Map 端先进行预聚合,极大减少 shuffle 数据量
rdd.reduceByKey(_ + _)

2. join 一定要提前 broadcast 小表,减少 shuffle

传统 join 如下,一定会 shuffle:

df1.join(df2, "id")

但如果 df2 是小表(小于 300MB),你应该这样写:

import org.apache.spark.sql.functions.broadcast

df1.join(broadcast(df2), "id")

本质就是:凡是小表 join,大胆 broadcast。

3. Shuffle 分区(spark.sql.shuffle.partitions)是性能关键

Spark 默认是 200 分区,这个值对大多数作业来说过大或过小。

我的经验:

数据量 推荐分区数
< 10GB 50~100
10~200GB 200~500
> 200GB 500~2000

设置方式:

--conf spark.sql.shuffle.partitions=300

千万不要盲目调大分区,否则:

  • 分区太多 → 调度时间爆炸
  • 分区太少 → 单分区数据倾斜

三、序列化:Spark 性能的隐形加速器

Spark 默认使用 Java 序列化,效率低、体积大,非常影响 shuffle 和 cache 效率。

一句话:强烈建议使用 Kryo。

开启 Kryo:

--conf spark.serializer=org.apache.spark.serializer.KryoSerializer
--conf spark.kryo.registrationRequired=false

如果你有自定义 class,可以手动注册,加速更多:

val conf = new SparkConf()
conf.registerKryoClasses(Array(classOf[MyClass]))

为什么 Kryo 这么重要?

  • 序列化速度比 Java 快 5~10 倍
  • 体积小 30%~60%
  • 直接提升 shuffle 和 cache 性能

我自己线上 ETL 作业切到 Kryo 后,整体性能提升了 25% 左右,非常划算。


四、一个真实案例:从 1 小时优化到 14 分钟

某业务的明细拉链作业每日增量约 80GB,最初 60 分钟跑不完。
我调优后压到了 14 分钟。优化手段如下:

1. 资源重配

从:

--executor-cores=8
--executor-memory=20G
--num-executors=10

改成:

--executor-cores=5
--executor-memory=10G
--num-executors=18

GC 秒降。

2. Broadcast 小表

原来:

df1.join(df2, Seq("uid", "date"))

改为:

df1.join(broadcast(df2), Seq("uid", "date"))

Shuffle 直接少一半。

3. Spark Shuffle 分区调小

从默认 200 → 调整为 300
结合 80GB 数据量效果刚刚好。

4. 序列化改为 Kryo

直接减少 shuffle 文件大小,带来 10~15% 性能收益。


五、最后说一句:调优没有银弹,但有套路

Spark 调优看起来复杂,其实就三个方向:

  1. 让资源配置更合理
  2. 减少 Shuffle,或者让 Shuffle 更轻量
  3. 让数据体积更小,序列化更高效

你只要掌握这三点,任何批处理作业你都能找到优化点。

而调优最核心的本质就是一句话:

你要理解 Spark 的执行方式,而不是调一堆参数希望它变快。

代码写得再优雅、框架再先进,只要你无脑 groupByKey、无脑大 Executor、无脑默认序列化,性能肯定救不回来。

目录
相关文章
|
3月前
|
资源调度 分布式计算 Kubernetes
分布式计算调度器浅谈:YARN、Kubernetes、Mesos 到底图啥?
分布式计算调度器浅谈:YARN、Kubernetes、Mesos 到底图啥?
145 4
|
3月前
|
Prometheus 分布式计算 监控
大数据指标和 SLA,那些你以为懂了其实没懂的事
大数据指标和 SLA,那些你以为懂了其实没懂的事
436 7
|
3月前
|
存储 自然语言处理 测试技术
一行代码,让 Elasticsearch 集群瞬间雪崩——5000W 数据压测下的性能避坑全攻略
本文深入剖析 Elasticsearch 中模糊查询的三大陷阱及性能优化方案。通过5000 万级数据量下做了高压测试,用真实数据复刻事故现场,助力开发者规避“查询雪崩”,为您的业务保驾护航。
1627 89
|
5月前
|
存储 消息中间件 Kafka
Confluent 首席架构师万字剖析 Apache Fluss(一):核心概念
Apache Fluss是由阿里巴巴与Ververica合作开发的Flink表存储引擎,旨在提供低延迟、高效率的实时数据存储与变更日志支持。其采用TabletServer与CoordinatorServer架构,结合RocksDB和列式存储,实现主键表与日志表的统一管理,并通过客户端抽象整合湖仓历史数据,弥补Paimon在实时场景下的性能短板。
796 22
Confluent 首席架构师万字剖析 Apache Fluss(一):核心概念
|
4月前
|
机器人 数据挖掘 API
一个销售数据分析机器人的诞生:看 Dify 如何在 DMS 助力下实现自动化闭环
Dify 作为一款低代码 AI 应用开发平台,凭借其直观的可视化工作流编排能力,极大降低了大模型应用的开发门槛。
569 22
一个销售数据分析机器人的诞生:看 Dify 如何在 DMS 助力下实现自动化闭环
|
3月前
|
存储 文字识别 数据可视化
实用代码工具:Python打造PDF选区OCR / 截图批量处理工具(支持手动/全自动模式)
一款基于Python的PDF区域OCR与截图工具,支持精准框选、文字识别、图片截取及Excel一键导出。内置手动审核与全自动批量处理模式,结合PyMuPDF、easyocr等技术,实现高效、可视化的PDF数据提取,适用于发票、报表等场景,显著提升办公效率。
446 11
|
6月前
|
存储 JSON 数据处理
Flink基于Paimon的实时湖仓解决方案的演进
本文源自Apache CommunityOverCode Asia 2025,阿里云专家苏轩楠分享Flink与Paimon构建实时湖仓的演进实践。深度解析Variant数据类型、Lookup Join优化等关键技术,提升半结构化数据处理效率与系统可扩展性,推动实时湖仓在生产环境的高效落地。
714 1
Flink基于Paimon的实时湖仓解决方案的演进
|
4月前
|
搜索推荐 JavaScript 关系型数据库
基于python大数据的高考志愿推荐系统
本研究基于数据挖掘技术,结合Django、Vue.js与MySQL等技术构建高考志愿推荐系统,整合高校信息与历年录取数据,通过算法模型为学生提供个性化、科学化的志愿填报建议,提升决策准确性与教育资源配置效率。
|
7月前
|
存储 分布式计算 Apache
湖仓一体:小米集团基于 Apache Doris + Apache Paimon 实现 6 倍性能飞跃
小米通过将 Apache Doris(数据库)与 Apache Paimon(数据湖)深度融合,不仅解决了数据湖分析的性能瓶颈,更实现了 “1+1>2” 的协同效应。在这些实践下,小米在湖仓数据分析场景下获得了可观的业务收益。
1235 9
湖仓一体:小米集团基于 Apache Doris + Apache Paimon 实现 6 倍性能飞跃