拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Hadoop Reduce OOM 真实排查案例(Hive On MapReduce)

本质脏数据 → 数据倾斜 → OOM业务背景用户行为日志每日离线跑批Hive 执行group by user_id统计用户行为次数。每日跑批某天作业突然失败Reduce 任务 OOM绝大多数 task 很快跑完仅 1 个 reduce 反复重试后 OOM 失败。报错日志java.lang.OutOfMemoryError: Java heap space Container killed by YARN for exceeding memory limits. AttemptID:attempt_xxxx_r_000012多次重试失败退出码143区分单纯调大内存只是临时掩盖本次根因上游埋点采集 bug 产生脏数据大量记录 user_id 字段输出同一个异常脏 key字符串-99999全部 shuffle 到同一个 reduce把 reduce 堆内存撑爆。不是代码逻辑错误是上游脏数据造成热点 key 倾斜引发 reduce OOM。一、完整排查步骤步骤 1YARN UI 观察现象确认是 Reduce 侧问题打开 ResourceManager 页面找到失败 Job看 Job 概览Map 100% 全部完成Reduce 卡在 99%只有一个 reduce task 反复失败其余几十个 reduce 几秒全部跑完。打开Counters → Map-Reduce Framework → Reduce input records。正常 reduce每个输入记录 2~5 万条。失败的 reduce12输入记录 1200 万条相差几百倍。 确认发生数据倾斜问题出在这个 reduce。Counter 只能看到数量看不到具体 key。步骤 2定位异常 Reduce 对应的 Container下载 task 日志Job 页面找到失败的 reduce taskIDr_000012点开 Attempts拿到 ContainerID。跳转该 NodeManager 节点下载reduce task 日志syslog/stderr。日志特征大量频繁 Full GCGC 时间占比极高大量重复打印同一个 key 值user_id-99999。此时定位热点脏 key‑99999。步骤 3回查原始 Hive 表验证脏数据执行 SQL 统计 key 分布确认脏 key 的量级select user_id,count(*) as cnt from dwd_user_log group by user_id order by cnt desc limit 5;输出表格user_idcnt-999991180 万135xxxx2.3 万136xxxx2.1 万确认上游埋点服务 bug部分设备上报时用户 ID 解析失败统一填默认值‑99999产生千万级脏 keyshuffle 全部落到同一个 reducereduce 迭代器把海量 value 加载进内存直接堆溢出 OOM。注意不是业务正常数据属于脏数据。步骤 4临时应急方案先让任务跑过保障调度方案 1过滤脏 key业务允许SQL 增加 where 条件select user_id,count(1) from dwd_user_log where user_id ! -99999 --过滤脏数据 group by user_id;临时应急任务直接跑通。方案 2如果业务不能直接过滤对脏 key 做加盐打散select if(user_id-99999,concat(user_id,_,floor(rand()*10)),user_id) as user_id_salt, count(1) from dwd_user_log group by if(user_id-99999,concat(user_id,_,floor(rand()*10)),user_id)把脏 key 打散到 10 个 reduce避免单 reduce 过载后续再做聚合合并结果。方案 3开启 hive.groupby.skewindatatrue拆两轮 MR 做自动倾斜处理消耗更多资源。❗不要优先只调大 reduce 内存mapreduce.reduce.memory.mb。就算调到 8G脏数据量继续涨早晚还会 OOM治标不治本。步骤 5根治源头防止次日再次发生通知埋点开发修复采集 bug不再生成‑99999异常 user_id。在数仓 DWD 层增加数据清洗逻辑过滤 / 标记该脏 key增加监控告警监控 user_id 分布某一个 key 行数超过阈值就告警。二、关键点为什么同一个 key 千万条记录会把 reduce OOMMR reduce 函数接收(key, Iterablevalue)shuffle 拉取过来该 key 全部的 value虽然 Iterable 是迭代读取但 shuffle 合并阶段大量数据会压入内存缓冲区当同一个 key 千万条内存缓冲区撑爆就报 Java heap space OOM。调大 reduce 内存能不能彻底解决不能。脏数据量持续增长再大内存也会被打满调内存只能临时续命根本要处理脏数据 / 热点 key。怎么区分是业务正常热点 key还是脏数据热点 key查询原始表看该 key 业务含义如果是异常默认值、null、异常编码就是脏数据如果是真实业务对象爆款商品、头部大用户属于业务热点。Counter 和日志分工再回顾Counter 看每个 reduce 输入记录数发现倾斜现象下载对应 Container 的 task 日志拿到真实热点 key。三、精简版线上遇到 Hive on MR 的 reduce OOM。现象是 map 全部跑完大部分 reduce 快速结束只有一个 reduce 反复重试 OOM。首先去 YARN UI 看 job 的 Counter 中 Reduce‑input‑records发现单个 reduce 输入千万条远大于其他 reduce确认倾斜。找到失败 reduce 对应的 Container下载 task 日志发现大量重复 key‑99999。回查源表统计 key 分布确认是上游埋点 bug 产生脏数据千万条记录 user_id 等于‑99999shuffle 全部落到同一个 reduce造成 OOM。应急在 SQL 过滤脏 key 先保障调度跑通同时通知上游修复埋点DWD 层增加清洗逻辑和分布监控从源头解决。没有单纯调大 reduce 内存因为调内存只是临时掩盖问题。四、延伸Spark 版本同类现象Spark 中对应现象Spark UI 某个 Stage少数 task 的 Shuffle Read 几百 MB‑GB 级别Executor 报 OOM排查思路看 task 的 Shuffle Read → 找到慢 task 对应 Executor 日志 → SQL 统计 key 分布定位脏 key。容易踩坑点看到 OOM 就直接加大 YARN 容器内存不去查数据分布任务后续还会失败。分不清容器被 YARN kill有两种情况JVM 堆 OOM物理内存超限堆外 进程占用要区分日志信息阿里云帮助...。脏数据不只是‑99999还有大量 null、空字符串、异常编码都会造成热点倾斜 OOM。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门