怎么排查由于在持久化层一二级缓存管理失控导致的堆内存不断蚕食

云磊大大_6114

云磊大大_6114

2026-05-19

374人浏览

原创

排查缓存导致堆内存持续增长,关键确认缓存对象是否长期滞留无法回收;重点检查mybatis一二级缓存配置与使用规范、key/value设计、过期策略缺失及spring cache误用,并通过mat分析引用链与运行时监控交叉验证。

怎么排查由于在持久化层一二级缓存管理失控导致的堆内存不断蚕食

排查持久化层一二级缓存管理失控导致的堆内存持续增长,核心在于确认“缓存对象是否长期滞留、无法被回收”,而非简单看内存用了多少。这类问题隐蔽性强——应用不报错、GC能运行、但堆内存曲线像爬坡一样缓慢上扬,尤其在长时间运行或定时任务触发后更明显。

盯住缓存类对象的生命周期和引用链

一级缓存(如 MyBatis 的 SqlSession 级别缓存)和二级缓存(如 Ehcache、Caffeine、Redis 客户端本地缓存)若配置不当或使用不规范,极易成为内存泄漏温床。重点检查:

  • MyBatis 一级缓存未及时清空:SqlSession 复用过久、未手动调用 clearCache(),或在长事务/循环中反复执行相同查询,导致结果集对象堆积在 SqlSession 内部的 PerpetualCache 中;
  • 二级缓存 Key 或 Value 无界增长:例如用 new Object() 或含业务实体的复杂对象作缓存 Key,未重写 equals/hashCode,造成大量重复 Key 实例;又或 Value 是未序列化/未清理的 VO/DTO,含对 Service、Mapper、甚至 ThreadLocal 的隐式引用;
  • 缓存未设置过期策略或最大容量:比如 Ehcache 配置了 timeToLiveSeconds=0(永不过期)且 maxEntriesLocalHeap 未设上限,数据越积越多;
  • Spring Cache 抽象层误用:@Cacheable 方法返回值为大对象(如 List),且未配置 unless 或条件淘汰逻辑,缓存命中率低但体积大,还可能因代理机制引入 AOP 相关的代理对象残留。

用 MAT 快速定位缓存相关对象

拿到堆转储(.hprof)后,在 MAT 中直接聚焦缓存行为特征:

  • 打开 Histogram,按包名筛选:org.apache.ibatis.cache、org.springframework.cache、com.github.benmanes.caffeine、net.sf.ehcache 等,看对应类实例数和保留集(Retained Heap)是否异常高;
  • 右键可疑类 → Merge Shortest Paths to GC Roots → exclude weak/soft references:这能过滤掉正常弱引用缓存项,暴露出那些被强引用锁死、无法回收的对象路径;常见罪魁是静态 Map、单例 CacheManager 持有未清理的 Entry、或线程局部变量(ThreadLocal)意外持有缓存句柄;
  • 查看 Dominator Tree,排序 Retained Heap,找排在前列但业务上不该长期存在的对象类型(如某次批量查询返回的 50 万条 Entity 列表),再追溯其 GC Roots,大概率指向某个缓存容器或静态上下文。

结合运行时行为做交叉验证

仅靠 dump 文件容易误判,需辅以动态观测:

  • 开启 MyBatis 日志(logging.level.org.apache.ibatis=DEBUG),观察同一 SQL 是否高频命中一级缓存(log 中出现 Cache Hit),同时检查该 SqlSession 是否被长期复用(如注入到单例 Service 中);
  • 对二级缓存组件启用统计开关:如 Caffeine 加 recordStats(),暴露 hitRate()、estimatedSize() 等指标,通过 Actuator / Prometheus 拉取,确认缓存是否“只进不出”;
  • 用 jcmd VM.native_memory summary 对比堆内与堆外内存增长趋势——若堆内存涨得快但堆外平稳,基本可排除 Netty Direct Buffer 类问题,进一步锁定是 Java 对象层缓存失控;
  • 临时加监控点:在关键缓存 put 操作前后打印 Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(),确认单次写入是否引发不可逆的内存抬升。

代码与配置层面的关键修复点

确认问题后,修复要直击根源,而非仅调大堆内存:

  • 一级缓存:避免跨请求复用 SqlSession;必要时在方法末尾显式 sqlSession.clearCache();慎用 flushCache=true 的更新语句,防止误清其他缓存;
  • 二级缓存:强制 Key 实现规范的 equals/hashCode;Value 尽量用轻量 DTO,避免携带 Spring 上下文或数据库连接;配置合理 maxSize 和 expireAfterWrite;
  • 禁用高风险默认行为:如 MyBatis 默认开启一级缓存,若业务明确不需要,可在配置中设 localCacheScope=STATEMENT;Spring Boot 中关闭自动配置的 SimpleCacheManager,改用显式声明带限流策略的缓存器;
  • 增加缓存健康检查:定期调用 Cache.getNativeCache() 获取底层实例,校验 size、hit rate 是否超出阈值,并记录告警。
PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

10777

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

7902

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

6852

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1164

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

948

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1396

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

2829

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

20131

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1255

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.8万人学习