某个Reduce卡了20分钟,你怎么排查和解决数据倾斜?
本文目录
先说结论
数据倾斜的排查分三步:
第一步:确认是不是倾斜 —— 看YARN的Application详情页,如果多数Reduce已完成但个别卡在99%不动,基本就是倾斜。
第二步:定位倾斜Key —— 看你的SQL里哪个GROUP BY或JOIN的Key分布不均匀。用COUNT + GROUP BY看数据分布。
第三步:根据场景选方案 —— 不同的倾斜场景有不同的解法。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
Hive里的数据倾斜是我做了9年大数据遇到最多的性能问题。这道题考察的不只是你知不知道解决方案,更重要的是你能不能系统地排查问题。很多人上来就说“加盐打散”,但面试官其实想听的是你“怎么发现倾斜、怎么定位原因、再怎么解决”的完整过程。
业务场景:按国家统计设备激活数
我在出海硬件公司做过一个报表:按国家统计每天的设备激活数。SQL很简单:
SELECT country, COUNT(DISTINCT device_id) AS active_devices
FROM dwd_device_event
WHERE dt = '2025-03-14'
GROUP BY country;
但这个作业跑了32分钟。打开YARN一看,19个Reduce都在2分钟内完成了,但有一个Reduce卡了30分钟。
排查过程:找到倾斜Key
先看数据分布:
SELECT country, COUNT(1) AS cnt
FROM dwd_device_event
WHERE dt = '2025-03-14'
GROUP BY country
ORDER BY cnt DESC
LIMIT 10;
结果发现:美国的数据量占总量的60%,其他国家加起来才40%。这意味着处理美国数据的那个Reduce要处理全场60%的数据,而其他Reduce平均只处理几个百分点。
场景一:GROUP BY倾斜的解决方案
这是最常见的倾斜场景。解法是开启两阶段聚合:
SET hive.map.aggr = true; -- 开启Map端聚合
SET hive.groupby.skewindata = true; -- 开启倾斜优化
开启hive.groupby.skewindata后,Hive会跑两次MapReduce:
第一次MR:按随机数分发数据,每个Reduce做局部聚合。原来美国的60%数据全去了一个Reduce,现在随机分散到所有Reduce。
第二次MR:按真正的Key(country)进行最终聚合。这时每个Reduce的数据量已经被第一次大幅压缩了。
本质就是“加盐打散”的自动版。开启后,这个作业从32分钟降到6分钟。
场景二:Join倾斜的解决方案
如果倾斜发生在Join操作中,常见原因是Join Key存在热点值,尤其是NULL值。
情况一:NULL值倾斜
比如user_id为NULL的匿名用户数据占了30%,所有NULL都被Hash到同一个Reduce。
-- 方案A:如果NULL不参与业务逻辑,直接过滤
SELECT * FROM a JOIN b ON a.user_id = b.user_id
WHERE a.user_id IS NOT NULL;
-- 方案B:如果NULL需要保留,给NULL加随机后缀打散
SELECT *
FROM (
SELECT COALESCE(user_id, CONCAT('null_', CAST(RAND()*100 AS INT)))
AS join_key, *
FROM table_a
) a
JOIN table_b b ON a.join_key = b.user_id;
情况二:非NULL的热点Key
比如某个头部主播的数据量远超其他主播。解法和Spark一样:加盐打散或拆分处理。
场景三:COUNT DISTINCT倾斜
这是很多人容易忽略的倾斜场景。COUNT(DISTINCT x)在Hive里只会用一个Reduce处理,数据量大时直接崩溃性地慢。
-- ✖ 慢:只有一个Reduce,全部数据挤在一起
SELECT COUNT(DISTINCT user_id) FROM user_log WHERE dt = '2025-03-14';
-- ✔ 快:先GROUP BY分散到多个Reduce,再COUNT
SELECT COUNT(1) FROM (
SELECT user_id FROM user_log
WHERE dt = '2025-03-14'
GROUP BY user_id
) t;
这个改写技巧面试里经常考。原理很简单:GROUP BY可以利用多个Reduce并行去重,而COUNT DISTINCT只能用一个。我在元宇宙社交App做DAU统计时,用这个改写把执行时间从15分钟降到2分钟。
实战踩坑:倾斜不一定是Key的问题
我在短剧出海公司遇到过一个特殊的倾斜:不是Key分布不均匀,而是某些分区的数据文件大小差异巨大。有个分区的数据集中在一个大文件里,导致读取这个文件的Map Task特别慢。解决方案是用repartition重新分布数据。
所以排查倾斜时不要只看Key分布,还要看文件大小分布。这个细节面试里说出来,非常加分。
总结
| 倾斜场景 | 解决方案 | 核心原理 |
|---|---|---|
| GROUP BY倾斜 | hive.groupby.skewindata=true | 两阶段聚合,第一次随机分发 |
| Join NULL倾斜 | 过滤NULL或加随机后缀 | 避免NULL全部去同一个Reduce |
| Join热点Key | 加盐打散/拆分处理 | 把热点Key打散到多个Reduce |
| COUNT DISTINCT | 改写为GROUP BY + COUNT | 利用多个Reduce并行去重 |
排查倾斜的核心是“先确认再定位再解决”。面试的时候能说出完整的排查过程,再针对不同场景给出不同方案,就很稳了。
下一篇聊一个数据质量的实战场景:下游报表数据异常,你怎么快速定位是哪层哪个作业出了问题?这是数据开发的日常。
你们遇到过最离谱的倾斜场景是什么?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长