一次OOM事故的学习过程

一次,oom,事故,学习,过程 · 浏览次数 : 216

小编点评

事故发生过程中,dump文件大小为42G。由于机器内存只有96G 16vCPU mat使用56G内存作为堆区分析dump文件分析42G的dump文件,分析结果堆区为27.5G,最大的一个现场使用23.3G的内存。 分析方法: 1. **分析堆区**:分析堆区分析42G的dump文件,发现最大的一个内存对象占用23.3G的内存。分析过程需要按照retained heap 的大小进行排序,打开最大占用内存的线程信息就可以。 2. **分析 dominator_tree**:分析 dominator_tree 里面会有响应的堆区内存的详细信息,需要按照retained heap 的大小进行排序。 3. **分析 SQL**:针对分析出来的业务功能去查看业务逻辑以及SQL等内容。 4. **分析 OOM 信息**:分析 OOM 信息,包括分析时间、OOM 的最大占用内存、与 CPU 关系、与内存大小和磁盘IO性能关系。 **优化建议:** 1. **调整 JVM 的堆区和GC类型的设置**:优化 JVM 的堆区和GC类型的设置,例如设置堆区大小、GC 算法、GC阈值等。 2. **关闭swap**:关闭swap,避免swap出现时磁盘读写降低系统性能。 3. **关闭OOM**:如果出现 OOM,可以尝试关闭一些非核心功能,例如日志记录、缓存等。 4. **提高服务器性能**:提高服务器性能,以降低 OOM 的发生频率和次数。 5. **使用高配置的机器**:如果服务器有高配置的机器,可以考虑使用这些机器进行分析。 **其他提示:** 1. **使用工具分析dump**:如果工具无法分析dump文件,可以尝试使用其他工具进行分析。 2. **分析大数据**:如果需要分析大数据,可以使用其他技术,例如 MapReduce、Spark 等框架。

正文


事故过程

周二下午得到消息, 希望帮忙分析dump文件.
告知dump大小为42G大小. 一般机器没这么大的内存进行处理.
建议现场上传到百度云盘, 然后我这边进行下载.
时间进度为:
11.57创建的dump
现场打包压缩, 拉取上传百度云盘. 速度大概只有500KB/S.
压缩后文件6G, 时间大约是 4小时左右上传完.
我这边接收到百度云盘已经晚上七点半.
下载耗时大约1h+
九点开始解析, 九点五十五分出结果.
分析情况:
机器内存 96G 16vCPU
mat使用56G内存作为堆区分析dump文件
分析42G的dump文件, 分析结果堆区为27.5G,最大的一个现场使用23.3G的内存.
分析耗时 50min. 

OOM的一些分析

dump解析完成只有
在overview 的截面处明显看到有一个巨大的内存对象.

左键最大的内存区域 打开java-basic 然后可以查看thread details
可以看到占用最大内存的区域是什么进程在使用.

因为mat 较为卡顿, 建议将整个堆栈区域复制出来进行分析. 
排除掉springboot java 以及类加载器相关的堆栈, 基本上就可以定位到是那一块业务代码
然后根据模块信息找到具体开发, 然后进一步存在具体的业务功能. 
针对分析出来的业务功能去查看业务逻辑以及SQL等内容. 

OOM的一些分析

注意 OOM 分析的时间跟CPU有关系也跟内存大小和磁盘IO性能有关系.
他分析过程中会形成大量的文件, 作为索引, 如果出现了停止响应, 可以杀掉进程
重新打开待分析的dump文件. 速度会比较快. 

分析完threads 之后 可以分析一下 dominator_tree 里面会有响应的堆区内存的详细信息.

需要按照retained heap 的大小进行排序, 打开最大占用内存的线程信息就可以.
一直选中占用内存最大对想进行展开. 
我这次例子中 hashmap的对象下面有多个hashmapnode 
简单统计了下:
没一个hashmap对象占用 3KB左右的内存空间. 一共先是有800多万个对象. 简单计算为:
3KB*8M=24GB. 很明显就可以将内存使用情况计算出来. 

然后继续打开每一个 hashmapnode 
发现第一个node的数值都是一样的, 将数据取出.放入第一步业务开发分析出来的SQL.
验证查询展示出来的数据结果集是否是八百万多. 

优化的方向

JVM的堆区和GC类型的设置还是需要关注
bean数量的差异,以及实例化对象多寡对内存的要求是不一样的. 
堆区,栈区,方法区,以及元数据区,还有直接内存还有系统自己剩余的内存
必须严格控制, 建议关闭swap, 避免swap出现时磁盘读写降低系统性能. 
建议服务器必须专用 堆区还是足够大比较好, 
足够大的堆区能够容忍部分垃圾代码, 和降低异常产生的频率和次数. 

不能因为OOM时dump文件过大就因噎废食. 可以通过改善工具的方式来解决问题
而不是为了好解决问题和不顾及问题发生的频率. 

分析优化

突然想这次OOM 可能不全通过dump分析应该也可以定位到. 
猜测一下分析方式: 
top -Hp threadid 查看占用CPU最多的进程信息
然后jstack -l 将堆栈信息打出
查看堆栈详细内容. 进行排查. 
理论上效率应该能快很多. 

另外建议现场有高配置的机器. 能够直接分析dump
没有人能够靠眼睛分析出来所有的问题. 必须有趁手的兵器才可以.

优化的方向

left join左连接产生的是笛卡尔积,
即两个10行的表左连接,首先是生成一个10*10行的表,
然后根据on后面的条件筛选符合条件的行。
消除笛卡尔乘积最根本的原因不是在于连接,而是在于唯一ID,
就像学号,一个学生就只有一个学号,学号就是这个学生的唯一标识码。
左连接只是以左边的表为基准,左边的ID和右边ID都是唯一,
就不会产生笛卡尔现象,如果右边有两个ID对应左边一个ID,
就算你是左连接,一样会产生1对多的现象。

SQL连接的简单学习

image


代码排查方面

简单数据的情况下不会有这样的问题.
但是如果连接的 关联条件查询出来的数据不唯一
会导致笛卡尔积,比两个表的数量都放大.  

业务SQL的严格准确很重要, 一定不要有笛卡尔积的结果出现.

本次例子里面两个子表 在同一个条件下 各有 2932条数据.
简单的笛卡尔积 就导致了接近 9m 的数据量. 
因为查询的结果集字段比较多, 导致一次查询就会使用 24GB的堆区
直接导致OOM

与一次OOM事故的学习过程相似的内容:

一次OOM事故的学习过程

事故过程 周二下午得到消息, 希望帮忙分析dump文件. 告知dump大小为42G大小. 一般机器没这么大的内存进行处理. 建议现场上传到百度云盘, 然后我这边进行下载. 时间进度为: 11.57创建的dump 现场打包压缩, 拉取上传百度云盘. 速度大概只有500KB/S. 压缩后文件6G, 时间

分布式事务提交慢的一次总结和思考

分布式事务提交慢的一次总结和思考 背景 分布式事务未提交 是应用程序出现宕机异常的很重要的一原因. 应用宕机主要可以分为: 1. 内存泄露导致的OOM宕机. 表现在系统越来越慢, 应用的内存和CPU占用量越来越高. 最终达到无响应的状态, 此时数据库一般是正常的. 2. 分布式事务未提交导致的宕机,

[转帖]一次 Java 进程 OOM 的排查分析(glibc 篇)

https://juejin.cn/post/6854573220733911048 遇到了一个 glibc 导致的内存回收问题,查找原因和实验的的过程是比较有意思的,主要会涉及到下面这些: Linux 中典型的大量 64M 内存区域问题 glibc 的内存分配器 ptmalloc2 的底层原理 如

[转帖]一次 Java 进程 OOM 的排查分析(glibc 篇)

https://juejin.cn/post/6854573220733911048 遇到了一个 glibc 导致的内存回收问题,查找原因和实验的的过程是比较有意思的,主要会涉及到下面这些: Linux 中典型的大量 64M 内存区域问题 glibc 的内存分配器 ptmalloc2 的底层原理 如

[转帖]总结:记一次K8S容器OOM案例

一、背景 最近遇到个现象,hubble-api-open组件过段时间会内容占满,从而被K8S强制重启。 让我困惑的是,已经设置了-XX:MaxRAMPercentage=75.0,我觉得留有了一定的空间,不应该会占满,所以想深究下原因。 -XX:MaxRAMPercentage是设置JVM的最大堆内

记一次字符串末尾空白丢失的排查 → MySQL 是会玩的!

开心一刻 今天答应准时回家和老婆一起吃晚饭,但临时有事加了会班,回家晚了点 回到家,本以为老婆会很生气,但老婆却立即从厨房端出了热着的饭菜 老婆:还没吃饭吧,去洗下,来吃饭吧 我洗好,坐下吃饭,内心感动十分;老婆坐旁边深情的看着我 老婆:你知道谁最爱你吗 我毫不犹豫道:你 老婆:谁最关心你? 我:你

记一次线上问题 → Deadlock 的分析与优化

开心一刻 今天女朋友很生气 女朋友:我发现你们男的,都挺单纯的 我:这话怎么说 女朋友:脑袋里就只想三件事,搞钱,跟谁喝点,还有这娘们真好看 我:你错了,其实我们男人吧,每天只合计一件事 女朋友:啥事呀? 我:这娘们真好看,得搞钱跟她喝点 问题复现 需求背景 MySQL8.0.30 ,隔离级别是默认

记一次 Redisson 线上问题 → ERR unknown command 'WAIT' 的排查与分析

开心一刻 昨晚和一个朋友聊天 我:处对象吗,咱俩试试? 朋友:我有对象 我:我不信,有对象不公开? 朋友:不好公开,我当的小三 问题背景 程序在生产环境稳定的跑着 直到有一天,公司执行组件漏洞扫描,有漏洞的 jar 要进行升级修复 然后我就按着扫描报告将有漏洞的 jar 修复到指定的版本 自己在开发

一次Java服务内存过高的分析过程

现象 年前,收到了短信报警,显示A服务的某台机器内存过高,超过80% 如上图所示,内存会阶段性增加。奇怪的是,十多台机器中只有这一台有这个问题 堆内内存分析 最先怀疑是内存泄漏的问题,所以首先使用jmap命令把堆dump下来 jmap -dump:format=b,file=service.hpro

[转帖]一次艰难的内存泄露排查

https://www.jianshu.com/p/d0dff28a4cce 一次艰难的内存泄露排查 现象 2019.4.26 22:00左右,通过jstat -gcutil pid 5000 ,发现fgc次数很多而且频繁,此时老年代占比已经大约70%左右,且已经回收不了内存,我们这边设置的fgc阈