忽视了MyBatis 默认开启二级缓存,Pod 内存飙升竟是它惹的祸!

内容分享8小时前发布 kempYu
0 0 0

【避坑指南】90% 开发者都忽视了!MyBatis 默认开启二级缓存,Pod 内存飙升竟是它惹的祸!

在许多 Spring Boot 项目中,我们习惯于用 MyBatis 做持久层框架。

但你知道吗?MyBatis 默认就打开了一个“隐形内存杀手”——二级缓存。

在高并发场景下,它足以让你的 Kubernetes Pod 内存直接炸掉 !


今天这篇文章,我们就彻底讲清楚这个坑:

✅ 为什么 MyBatis 会让 Pod 内存暴涨

✅ 如何合理配置 MyBatis 缓存

✅ 高并发下的生产最佳实践

✅ 一行配置,让内存直接降 70%


一、MyBatis 缓存机制全景图

MyBatis 内置两级缓存体系:

缓存级别

作用范围

默认状态

存储位置

特点

一级缓存(Local Cache)

SqlSession 级别

✅ 默认开启

JVM 内存(线程安全)

轻量缓存,每个会话独立

二级缓存(Mapper 缓存)

Namespace 级别

✅ 默认开启

JVM 堆内存

多线程共享,数据常驻

翻译成人话:

一级缓存相当于“线程内临时记忆”,

二级缓存相当于“每个 Mapper 一个巨大仓库”。

在单体项目中,这没什么问题。

但当你上云部署到 Kubernetes,高并发 + 多副本 + Mapper 多时,这个“仓库”就成了 内存炸弹


⚙️ 二、默认状态揭秘:实则你根本没关掉它!

许多开发者以为:

“我没配置 cache-enabled,应该默认是关的吧?”

❌ 实际上 MyBatis 在源码里已经写死了:

this.cacheEnabled = true; // 默认开启

也就是说:

只要你不手动关闭,它就在默默吃你的内存。

Spring Boot 的 MyBatis 自动装配并不会覆盖这个默认行为,

这意味着每个 Mapper 的查询结果(ResultMap)都可能被缓存到内存中。


三、高并发场景下的“内存雪崩”

举个简单的例子:

  • 你有 30 个 Mapper
  • 每个 Mapper 查询结果平均 10MB
  • 系统高并发请求频繁更新缓存

结果就是:

30 × 10MB = 300MB(仅缓存数据)

再加上:

  • Tomcat 线程池 1000
  • MyBatis 一级缓存临时对象
  • 序列化反射对象占用

最终导致:

JVM 内存暴涨 → GC 疯狂打转 → Full GC 卡顿 → Pod 被 OOMKilled!


四、生产环境最佳配置方案(直接抄)

为了防止缓存导致内存爆炸,提议生产环境配置:

mybatis:
  configuration:
    cache-enabled: false              # ❌ 关闭二级缓存
    local-cache-scope: statement      # ✅ 仅在当前语句级缓存
    aggressive-lazy-loading: false    # 禁用激进懒加载
    lazy-loading-enabled: true        # 按需加载
    default-statement-timeout20     # 超时保护
    default-fetch-size400           # 限制结果集大小

优点:

✅ 内存占用大幅下降

✅ GC 频率下降 60%+

✅ 查询数据始终最新

✅ Pod 稳定性显著提升


五、搭配高并发优化策略更稳!

光关缓存还不够,这些配置一起上:

⚙️ Hikari 连接池优化

spring:
  datasource:
    hikari:
      maximum-pool-size50
      minimum-idle10
      max-lifetime300000
      connection-timeout10000

Tomcat 并发调优

server:
  tomcat:
    max-threads500
    accept-count500

JVM 参数优化

-Xms512m -Xmx1024m -XX:+UseG1GC -XX:MaxGCPauseMillis=200

SQL 性能监控

开启 MyBatis SQL 日志或接入 Prometheus Exporter 监控慢查询与命中率。


六、总结对比表

缓存类型

默认状态

是否推荐生产开启

缘由

一级缓存

✅ 开启

✅ 推荐

轻量、线程内安全

二级缓存

✅ 开启

❌ 禁用

内存占用高、无过期机制


七、一句话总结

“MyBatis 的二级缓存默认是开的。

在高并发 Kubernetes 环境里,它不是加速器,而是内存炸弹。”

© 版权声明

相关文章

暂无评论

none
暂无评论...