订阅更新

一个Task跑了40分钟,其他Task早就结束了——什么是数据倾斜?

数据倾斜手册 第 1 题 约 9 分钟读完

本文目录
  1. 先说结论
  2. 用一个真实案例理解数据倾斜
  3. 数据倾斜发生在哪个阶段?
  4. 如何从Spark UI确认数据倾斜?
  5. 数据倾斜 vs 资源不足——怎么区分?
  6. 面试高频追问
  7. 实战踩坑
  8. 总结

先说结论

数据倾斜的本质:数据在分区间分布严重不均,导致少数Task处理了绝大多数数据,成为整个作业的瓶颈。

判断标准:Spark UI里某个Stage,99%的Task在几十秒内完成,但有1-3个Task跑了几十分钟,这就是典型的数据倾斜。

根源:分区键的值分布不均匀。某些key对应的数据量远远超过其他key,而Shuffle是按key分发数据的,同一个key的所有数据必须去同一个Task处理。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

数据倾斜是大数据面试里出现频率最高的话题之一。几乎每次面试都会问到,而且问法越来越深:从「什么是数据倾斜」到「你遇到过什么倾斜,怎么解决的」,再到「为什么你选这个方案而不是那个方案」。这篇先把基础打扎实——搞清楚什么是数据倾斜、它是怎么发生的、为什么这么难发现。

用一个真实案例理解数据倾斜

我在某出海硬件品牌做设备激活数据分析时,遇到过一次典型的数据倾斜。我们有一张device_events表,记录每台设备的行为事件。有一次做GROUP BY device_id的统计,整个Stage有500个Task,497个Task在2分钟内全部跑完,但有3个Task卡了快40分钟才结束。

去Spark UI一看,这3个Task处理的数据量是其他Task的400倍。再一排查,发现这3个超大Task对应的device_id都是测试设备——我们公司的QA团队用这几台设备持续跑自动化测试,产生了海量事件,占总数据量的30%以上。这就是典型的数据倾斜:key分布不均导致分区数据量极度不均衡。

-- 发现倾斜前,先看数据分布
SELECT
  device_id,
  COUNT(*) AS event_count,
  COUNT(*) * 100.0 / SUM(COUNT(*)) OVER() AS pct  -- 占总量百分比
FROM device_events
GROUP BY device_id
ORDER BY event_count DESC
LIMIT 20;
 
-- 如果TOP 5的device_id占了总量60%以上,基本可以确认倾斜
-- 我们当时发现3个测试设备device_id占了总数据的32%

这个排查思路很重要:遇到作业慢,别急着加资源,先看数据分布。如果数据分布是均匀的,那就是资源不足或代码问题;如果数据分布极度不均匀,那就是倾斜,加资源没用。

数据倾斜发生在哪个阶段?

数据倾斜只发生在需要Shuffle的操作里。没有Shuffle就不会有倾斜,因为Shuffle才会按key把数据分发到不同的Task。常见的会触发Shuffle的操作有:

操作类型典型算子倾斜风险
分组聚合GROUP BY, groupByKey, reduceByKey⭐⭐⭐ 高
JOINjoin, leftJoin(非Broadcast)⭐⭐⭐ 高
去重DISTINCT, dropDuplicates⭐⭐ 中
排序ORDER BY, sortByKey⭐⭐ 中
重分区repartition(如果指定key)⭐⭐ 中
映射/过滤SELECT, WHERE, filter, map✗ 不触发Shuffle

JOIN导致的倾斜最难排查,因为倾斜可能来自大表,也可能来自小表的某些超大key,情况更复杂。后面几篇会专门拆解JOIN倾斜的处理方法。

如何从Spark UI确认数据倾斜?

判断是否存在数据倾斜,不能靠感觉,要去Spark UI看数据。以下是标准排查步骤:

# 打开Spark UI(默认端口4040,集群模式看YARN UI)
# 路径:Jobs → 点进慢的Job → 点进慢的Stage → Tasks列表
 
# 重点关注以下指标:
# 1. Duration列:Task执行时间是否有极端值
# 2. Input Size列:各Task读取的数据量是否差异巨大
# 3. Shuffle Read Size列:各Task的Shuffle Read量差异
# 4. GC Time列:GC时间长说明内存撑满了,间接证明数据量大
 
# 判断倾斜的经验标准:
# - 最慢Task的时间 > 平均时间 × 5倍 → 轻度倾斜
# - 最慢Task的时间 > 平均时间 × 10倍 → 严重倾斜
# - 最大Task的数据量 > 平均数据量 × 10倍 → 严重倾斜

有一个误区要注意:Task执行时间长,不一定就是数据倾斜。也可能是某个Task所在的Executor遇到了GC风暴,或者该节点磁盘IO慢。区别方法:如果是倾斜,Task处理的数据量(Input Size / Shuffle Read Size)也会很大;如果是机器问题,数据量正常但时间很长。

数据倾斜 vs 资源不足——怎么区分?

很多人一看作业慢就加资源(加Executor个数、加内存),但如果根本原因是数据倾斜,加资源完全没用。区分标准:

现象数据倾斜资源不足
Task完成时间大部分快完成,少数极慢所有Task都慢,差异不大
Spark UITask数据量差异极大Task数据量相对均匀
作业Hang住最后1-2个Task一直跑整个Stage都慢
加资源效果没用,倾斜Task还是慢有效,整体加速
GC情况倾斜Task的GC时间超长所有Executor GC都多

记住这个口诀:大部分Task快,少数Task卡,一定先查数据分布,别急着加资源。

面试高频追问

追问一:数据倾斜为什么会导致OOM?

因为同一个key的所有数据必须被同一个Task处理,而这些数据在聚合或JOIN之前要先放在内存里(Shuffle Read阶段)。如果某个key的数据量超大,单个Executor的内存放不下,就会触发OOM。这就是为什么数据倾斜有时候不只是慢,而是直接报错。我在某元宇宙社交应用做实时数仓时,有个按user_id做聚合的Flink作业,某个压测账号产生了海量数据,直接导致对应的Slot OOM,作业崩了。

追问二:什么情况下数据倾斜是「无解」的?

业务逻辑要求把某个超大key的所有数据放在一起处理时,比如统计某个全局热门商品的所有用户行为,这个商品就是一个超大key。这种情况下我们没办法拆分数据,只能:1)提前过滤掉这个key做特殊处理;2)把这个key单独拉出来用另一条链路处理;3)重新思考业务需求,是否真的需要精确计算。面试时能说出「无解的倾斜要从业务需求层面重新思考」,会让面试官觉得你有架构全局观,不只是个调参侠。

追问三:Flink里有数据倾斜吗?和Spark的倾斜有什么区别?

有。Flink里按key分区做keyBy之后,同样会导致数据量大的key对应的SubTask数据量超大。区别在于:Spark是批处理,一个Stage里所有Task并行跑完才继续,倾斜的Task会拖慢整个Stage;Flink是流处理,倾斜的SubTask会持续高负载,导致反压,最终影响整个流水线的吞吐,严重时触发Checkpoint超时作业崩溃。处理思路类似,但Flink更多用两阶段聚合(局部聚合+全局聚合)来解决。

实战踩坑

我在某出海硬件品牌做EMR到Databricks迁移时,迁移完一批作业后发现有一个设备激活报表作业,在EMR上跑30分钟,迁到Databricks上反而跑了40分钟。我第一反应是Spark版本差异导致的,调了一堆配置参数都没用。

最后还是去Spark UI仔细看,发现有3个Task的执行时间是其他Task的20倍,而这3个Task的Shuffle Read数据量是其他Task的400倍。再查数据分布,发现是3个测试设备的device_id造成的倾斜——在EMR上这个倾斜也存在,但由于EMR的机器配置更高(更多内存),倾斜Task虽然慢但能撑住;到了Databricks的标准配置机器上,内存小了,倾斜Task开始频繁GC,反而更慢了。

-- 排查后,针对测试设备做过滤处理
-- 方案:把测试设备单独识别出来,主链路过滤掉
SELECT
  d.device_id,
  d.device_type,
  COUNT(e.event_id) AS event_count
FROM device_events e
JOIN device_meta d ON e.device_id = d.device_id
WHERE d.is_test_device = 0  -- 过滤掉测试设备,消除倾斜源
  AND e.event_date = '2023-06-01'
GROUP BY d.device_id, d.device_type;
 
-- 处理后:作业从40分钟降到8分钟
-- 测试设备数据单独走另一条链路统计(不影响业务指标)

教训:迁移作业时不要假设「在A环境能跑,到B环境也一样」。应该先做作业画像——记录每个作业在原环境的Task分布、数据量分布、慢Task比例,迁移后对比差异,才能快速定位问题。

总结

数据倾斜的本质是Shuffle按key分发数据,导致key分布不均时某些Task数据量暴增。判断倾斜去Spark UI看Task的Duration和数据量分布,大多数快少数慢才是倾斜,所有都慢是资源不足。面试时能把「倾斜的本质→触发Shuffle操作→判断方法→和资源不足的区别」说清楚,基础分就稳了。

下一篇聊最经典的倾斜场景——GROUP BY倾斜:为什么COUNT(DISTINCT)特别容易倾斜?有什么专属解法?

你们生产环境遇到过最严重的数据倾斜是什么场景?Task时间差了多少倍?评论区分享一下~

关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长

刷题进度保存在当前浏览器