3. 数据倾斜诊断工具
做数据倾斜调优,最怕什么?
不是问题有多复杂,而是你连「到底哪里倾斜了」都看不出来。
我见过不少团队,一遇到任务慢就盲目加资源,结果 Spark 的 Executor 从 10 个加到 100 个,倾斜的 Task 还是跑 2 小时。说白了,工具就在手边,但很多人没看懂它给的信号。
这一章,我就带你把这三大诊断工具吃透:Spark UI、Hive Explain、Flink Web Dashboard。每个工具我都会结合真实踩坑经历来讲,保证你学完就能用。
核心观点:诊断工具是你的「眼睛」。学会看,比学会调更重要。调优 80% 的时间应该花在诊断上,而不是盲目改代码。
3.1 Spark UI:Stage、Task、Shuffle 三页定乾坤
Spark UI 是我用得最多的诊断工具,没有之一。它把一次作业的执行过程拆成了三个关键页面,你只要盯住这三个地方,倾斜问题基本无所遁形。
3.1.1 Stage 页面:一眼看出「谁在拖后腿」
打开 Spark UI,先看 Stages 标签页。这里列出了所有 Stage,每个 Stage 后面有个「Duration」列。
正常情况,所有 Stage 的耗时应该差不多。如果某个 Stage 的耗时是其他 Stage 的 5 倍甚至 10 倍,那基本可以断定——这个 Stage 内部发生了数据倾斜。
我的经验:有一次我优化一个 ETL 任务,发现 Stage 3 跑了 45 分钟,而其他 Stage 平均只要 3 分钟。点进去一看,Shuffle Read 阶段有 3 个 Task 各读了 2GB 数据,其余 Task 只读了 50MB。这就是典型的「长尾效应」——少数 Task 撑起了整个 Stage 的耗时。
3.1.2 Task 页面:数据分布一目了然
点进有问题的 Stage,你会看到 Tasks 列表。这里有两个关键指标:
- Shuffle Read Size / Records:每个 Task 读取的数据量。如果最大值和最小值相差超过 3 倍,就要警惕了。
- Duration:每个 Task 的执行时间。倾斜的 Task 通常耗时是平均值的 5 倍以上。
我习惯按「Shuffle Read Size」降序排列,一眼就能看到「数据胖子」是谁。你想想看,如果 100 个 Task 里,有 3 个 Task 各读了 1GB,其余 97 个只读了几十 MB,这不就是典型的 Key 分布不均吗?
注意:不要只看 Duration。有时候 Task 跑得慢不是因为数据量大,而是因为 GC 频繁或资源竞争。一定要结合 Shuffle Read Size 一起看,才能准确定位。
3.1.3 Shuffle Read/Write:倾斜的「照妖镜」
Shuffle 阶段是数据倾斜的高发区。在 Spark UI 的 Stages 页面,每个 Stage 都有「Shuffle Read」和「Shuffle Write」两个指标。
| 指标 | 正常值 | 倾斜信号 |
|---|---|---|
| Shuffle Write (单个 Task) | < 200 MB | > 500 MB,且与其他 Task 差距大 |
| Shuffle Read (单个 Task) | < 300 MB | > 1 GB,且出现长尾 |
| Shuffle Spill (磁盘溢出) | 0 或很小 | 大量 Spill,说明内存不够或数据倾斜 |
我曾经遇到一个案例:Shuffle Write 阶段,某个 Task 写了 2.5GB 数据到磁盘,而其他 Task 平均只写了 100MB。点进去一看,这个 Task 处理的 Key 是空字符串——因为上游数据清洗没做,大量空值被 group by 到了同一个分区。这就是典型的「空值倾斜」。
3.2 Hive Explain:执行计划的「X 光机」
Hive 的 EXPLAIN 命令,很多人觉得它晦涩难懂,就跳过了。但我告诉你,这是诊断 Hive 数据倾斜最直接的武器。
3.2.1 怎么看懂执行计划
在 Hive CLI 或 Beeline 里执行:
EXPLAIN EXTENDED SELECT key, COUNT(*) FROM table GROUP BY key;
输出会包含三大部分:
- STAGE DEPENDENCIES:Stage 之间的依赖关系,告诉你哪些 Stage 可以并行,哪些必须串行。
- STAGE PLANS:每个 Stage 内部的算子细节,包括 Map 操作、Reduce 操作、Join 类型等。
- Statistics:Hive 预估的输入输出数据量,如果预估偏差很大,说明统计信息不准。
关键点:在 STAGE PLANS 里,找到 Reducer 或 Map Join 相关的算子。如果看到 Group By Operator 后面跟着 mode=mergepartial,说明 Hive 在做两阶段聚合——这是 Hive 自动优化的倾斜处理策略。
3.2.2 如何从计划中识别倾斜风险
我总结了一个「三步看计划」的方法:
- 看 Join 类型:如果 EXPLAIN 输出里是
Map Join,一般不会倾斜;如果是Reduce Side Join或Common Join,就要小心了——所有数据都要经过 Shuffle。 - 看 Reducer 数量:Hive 会根据数据量估算 Reducer 数。如果 Reducer 数很少(比如只有 1 个),而数据量很大,那这个 Reducer 就是「单点瓶颈」。
- 看数据倾斜标记:在 EXPLAIN EXTENDED 的输出里,有时会出现
SKEW或skewed字样,这是 Hive 在告诉你:「嘿,这里的数据分布可能有问题!」
避坑指南:我曾经遇到一个 SQL,EXPLAIN 显示 Reducer 数为 1,但数据量有 10 亿行。我以为是 Hive 统计信息不准,手动设置了 mapred.reduce.tasks=100。结果跑完一看,还是只有一个 Reducer 在干活——因为 GROUP BY 的 Key 只有 3 个唯一值,Hive 强制把所有数据路由到了 3 个 Reducer 上,而其中一个 Reducer 处理了 80% 的数据。所以,Reducer 数 ≠ 并行度,关键要看 Key 的基数。
3.3 Flink Web Dashboard:实时流的「心电图」
Flink 的 Web Dashboard 和 Spark UI 风格不太一样。它更侧重「实时」和「流式」的监控。如果你做的是实时数仓或流计算,这个工具你必须会用。
3.3.1 SubTask 指标:谁在「偷懒」
打开 Flink Dashboard,进入某个 Job,点击 Task Managers 或 SubTasks 标签页。你会看到每个 SubTask 的:
- Records Received / Sent:接收和发送的记录数。如果某个 SubTask 接收的记录数远大于其他 SubTask,说明上游数据分发不均匀。
- Bytes Received / Sent:数据量大小。和 Spark 一样,看最大值和最小值的差距。
- Duration:处理时间。倾斜的 SubTask 通常处理时间更长。
我习惯把 SubTask 列表按「Bytes Received」排序,一眼就能看出数据分布是否均匀。如果某个 SubTask 接收了 80% 的数据,那不用怀疑——KeyBy 策略出了问题。
3.3.2 Watermark 延迟:倾斜的「间接信号」
Flink 的 Watermark 是衡量事件时间进度的指标。如果某个 SubTask 的 Watermark 明显落后于其他 SubTask,说明这个 SubTask 处理速度慢,数据积压了。
为什么会这样?大概率是因为这个 SubTask 处理的数据量更大,或者遇到了热点 Key。
注意:Watermark 延迟也可能是反压导致的。要区分是「数据倾斜」还是「反压」,可以看 BackPressure 标签页。如果所有 SubTask 都显示高反压,那是资源不足;如果只有个别 SubTask 高反压,那才是数据倾斜。
3.3.3 反压监控:倾斜的「报警器」
Flink 的反压监控非常直观。在 Dashboard 的 BackPressure 标签页,每个 SubTask 会显示一个颜色:
- 绿色:正常,无反压。
- 黄色:轻度反压,需要关注。
- 红色:严重反压,数据已经堵住了。
如果某个 SubTask 长期显示红色,而它的上下游都是绿色,那基本可以断定——这个 SubTask 就是倾斜点。
我的经验:有一次排查 Flink 作业延迟,Dashboard 显示所有 SubTask 都是绿色,但 Watermark 就是不动。后来我点开 Metrics 标签页,发现有个 SubTask 的 numRecordsInPerSecond 是 0——它根本没收到数据!原来是因为 KeyBy 时用了 hash(key) % parallelism,而某个 Key 的 hash 值恰好映射到了一个不存在的 SubTask 上。这种「空转」问题,不看细粒度指标根本发现不了。
3.4 三大工具对比:什么时候用哪个?
| 场景 | 首选工具 | 看什么指标 |
|---|---|---|
| 离线批处理(Spark) | Spark UI | Stage Duration、Shuffle Read Size、Task 长尾 |
| 离线批处理(Hive) | Hive Explain | Reducer 数、Join 类型、SKEW 标记 |
| 实时流处理(Flink) | Flink Web Dashboard | SubTask 数据量、Watermark 延迟、反压颜色 |
| 不确定是哪个引擎 | 先看日志 | WARN/ERROR 日志中的倾斜提示 |
说白了,工具只是手段。你真正要培养的,是「看到异常指标 → 联想到数据倾斜 → 快速定位热点 Key」的思维链路。这一章讲的是「怎么看」,下一章我会讲「怎么治」——但前提是,你得先学会用这些工具把问题找出来。
本章小结:
- Spark UI 盯住 Stage 耗时、Task 数据分布、Shuffle Read/Write 三个页面。
- Hive Explain 重点看 Reducer 数、Join 类型和 SKEW 标记。
- Flink Dashboard 关注 SubTask 数据量、Watermark 延迟和反压颜色。
- 诊断是调优的第一步,花 80% 的时间在诊断上,调优才能事半功倍。