当前位置: 首页 > news >正文

【MyBatis-7】深入理解MyBatis二级缓存:提升应用性能的利器

在现代应用开发中,数据库访问往往是性能瓶颈之一。作为Java生态中广泛使用的ORM框架,MyBatis提供了一级缓存和二级缓存机制来优化数据库访问性能。本文将深入探讨MyBatis二级缓存的工作原理、配置方式、使用场景以及最佳实践,帮助开发者充分利用这一特性提升应用性能。

1. MyBatis缓存概述

MyBatis提供了两级缓存机制:

  1. 一级缓存:SqlSession级别的缓存,默认开启,作用范围限于同一个SqlSession内
  2. 二级缓存:Mapper级别的缓存,需要手动配置,多个SqlSession可以共享
// 一级缓存示例
SqlSession session1 = sqlSessionFactory.openSession();
User user1 = session1.selectOne("getUser", 1);  // 查询数据库
User user2 = session1.selectOne("getUser", 1);  // 从一级缓存获取
session1.close();// 二级缓存示例
SqlSession session2 = sqlSessionFactory.openSession();
User user3 = session2.selectOne("getUser", 1);  // 查询数据库
session2.close();SqlSession session3 = sqlSessionFactory.openSession();
User user4 = session3.selectOne("getUser", 1);  // 从二级缓存获取
session3.close();

2. 二级缓存工作原理

2.1 缓存结构

MyBatis二级缓存采用装饰器模式设计,核心组件包括:

  • Cache接口:定义了缓存的基本操作
  • PerpetualCache:基础的缓存实现,使用HashMap存储
  • 各种装饰器:如LruCache、FifoCache、ScheduledCache等,提供额外功能

2.2 工作流程

  1. 查询时先检查二级缓存
  2. 缓存命中则直接返回结果
  3. 未命中则查询数据库,并将结果存入二级缓存
  4. 执行insert/update/delete操作时,清空对应namespace的缓存
查询操作
二级缓存是否存在
返回缓存结果
查询数据库
结果存入二级缓存
返回结果
更新操作
清空对应namespace缓存

3. 二级缓存配置与使用

3.1 全局开启二级缓存

在mybatis-config.xml中配置:

<settings><setting name="cacheEnabled" value="true"/>
</settings>

3.2 Mapper级别配置

在Mapper XML文件中添加<cache>标签:

<mapper namespace="com.example.mapper.UserMapper"><cache eviction="LRU"flushInterval="60000"size="1024"readOnly="true"/><select id="selectUser" resultType="User" useCache="true">SELECT * FROM user WHERE id = #{id}</select>
</mapper>

3.3 缓存属性详解

  • eviction:缓存回收策略

    • LRU - 最近最少使用(默认)
    • FIFO - 先进先出
    • SOFT - 软引用
    • WEAK - 弱引用
  • flushInterval:缓存刷新间隔(毫秒)

  • size:缓存对象数量

  • readOnly:是否只读(true/false)

3.4 注解方式配置

@CacheNamespace(eviction = LruCache.class,flushInterval = 60000,size = 1024,readWrite = true
)
public interface UserMapper {@Select("SELECT * FROM user WHERE id = #{id}")@Options(useCache = true)User selectUser(Integer id);
}

4. 二级缓存的注意事项

4.1 脏读问题

由于二级缓存是跨SqlSession的,在多表关联或分布式环境下容易出现脏读。解决方案:

  • 对查询结果变化频率高的表禁用二级缓存
  • 使用<cache-ref>让关联的Mapper共享同一个缓存空间
  • 在更新操作多的场景下慎用

4.2 序列化要求

当readOnly=false时,从缓存中获取的对象是副本,要求对象必须实现Serializable接口。

4.3 缓存失效策略

MyBatis的缓存失效策略较为简单,任何修改操作都会清空整个namespace的缓存,可能导致缓存命中率下降。

5. 高级特性与集成

5.1 自定义缓存实现

MyBatis支持集成第三方缓存库,如Ehcache、Redis等:

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

5.2 缓存刷新策略

可以通过flushCache属性控制特定语句是否刷新缓存:

<select id="selectUser" resultType="User" flushCache="false">SELECT * FROM user WHERE id = #{id}
</select><update id="updateUser" parameterType="User" flushCache="true">UPDATE user SET name=#{name} WHERE id=#{id}
</update>

5.3 局部缓存禁用

对于某些特定查询可以禁用缓存:

<select id="selectRealTimeData" resultType="Data" useCache="false">SELECT * FROM realtime_data WHERE id = #{id}
</select>

6. 性能优化建议

  1. 合理设置缓存大小:根据应用内存情况调整size参数
  2. 选择合适的回收策略:根据数据访问模式选择LRU或FIFO
  3. 设置适当的刷新间隔:对实时性要求高的数据设置较短的flushInterval
  4. 监控缓存命中率:通过日志或监控工具评估缓存效果
  5. 分布式环境考虑:在集群部署时使用Redis等分布式缓存实现

7. 二级缓存 vs 一级缓存

特性一级缓存二级缓存
作用范围SqlSession级别Mapper级别
默认开启需要手动配置
共享性不共享多个SqlSession共享
存储结构内存可配置(内存/外部缓存)
生命周期SqlSession结束即销毁可持久化

8. 实际应用案例

电商平台商品展示优化

<!-- 商品Mapper配置 -->
<mapper namespace="com.example.mapper.ProductMapper"><cache eviction="LRU"flushInterval="3600000"  <!-- 1小时刷新 -->size="5000"readOnly="true"/><!-- 热门商品查询 --><select id="selectHotProducts" resultType="Product" useCache="true">SELECT * FROM products WHERE status = 'ACTIVE' ORDER BY sales_volume DESC LIMIT 100</select>
</mapper><!-- 商品分类Mapper -->
<mapper namespace="com.example.mapper.CategoryMapper"><cache-ref namespace="com.example.mapper.ProductMapper"/>
</mapper>

此配置将:

  1. 缓存热门商品数据1小时
  2. 商品分类与商品共享缓存空间
  3. 使用LRU策略管理缓存
  4. 只读模式提高读取性能

9. 常见问题解答

Q1:为什么我的二级缓存没有生效?
A1:请检查:

  1. mybatis-config.xml中cacheEnabled是否为true
  2. Mapper XML中是否添加了标签
  3. 是否在不同的SqlSession中测试
  4. 是否执行了更新操作导致缓存被清空

Q2:如何清空二级缓存?
A2:可以通过代码清空:

sqlSession.clearCache();  // 清空一级缓存
// 清空二级缓存需要获取对应Mapper的Cache对象
Cache cache = sqlSession.getConfiguration().getCache("com.example.mapper.UserMapper");
if (cache != null) {cache.clear();
}

Q3:二级缓存会导致内存溢出吗?
A3:如果缓存对象过多或没有合理设置size参数,确实可能导致OOM。建议:

  1. 合理设置size限制
  2. 对于大对象考虑使用SOFT/WEAK回收策略
  3. 监控缓存内存使用情况

10. 总结

MyBatis二级缓存是提升应用性能的有效工具,但需要根据具体业务场景合理配置。关键点包括:

  1. 理解二级缓存的工作原理和适用场景
  2. 掌握各种配置参数及其影响
  3. 注意缓存一致性问题
  4. 结合监控不断优化缓存策略

正确使用二级缓存可以显著减少数据库访问,提高系统响应速度,但过度依赖缓存也可能带来一致性问题。希望本文能帮助开发者在性能和一致性之间找到平衡点,构建高效的MyBatis应用。

相关文章:

  • 从0开始学习大模型--Day05--理解prompt工程
  • STL-list
  • DA14585墨水屏学习
  • LLMs之ChatGPT:《Connecting GitHub to ChatGPT deep research》翻译与解读
  • [学习]RTKLib详解:sbas.c与rtcm.c
  • cursor sign in 网页登录成功,sursor软件里一直登陆不成功没有登陆信息
  • 扫雷革命:矩阵拓扑与安全扩散的数学之美
  • [架构之美]Spring Boot多环境5种方案实现Dev/Test/Prod环境隔离
  • 二、Hive安装部署详细过程
  • 深度学习中的目标检测:从 PR 曲线到 AP
  • 各种音频产品及场景总结
  • 【生存技能】ubuntu 24.04 如何pip install
  • 好用的播放器推荐
  • MySQL索引详解(上)(结构/分类/语法篇)
  • expo多网络请求设定。
  • Pycharm(二十)张量的运算与操作
  • 泛型加持的策略模式:打造高扩展的通用策略工具类
  • 流动式起重机Q2考试的实操部分,重点复习内容包括哪些方面?
  • 嵌入式学习--江协51单片机day4
  • 【Linux系统】从零开始构建简易 Shell:从输入处理到命令执行的深度剖析
  • 韩国前国务总理韩德洙加入国民力量党
  • 古埃及展进入百天倒计时,闭幕前168小时不闭馆
  • 七大交响乐团在沪“神仙斗法”,时代交响奏出何等时代新声
  • 正荣地产:前4个月销售14.96亿元,控股股东已获委任联合清盘人
  • 公示!17个新职业、42个新工种亮相
  • 习近平离京赴莫斯科对俄罗斯进行国事访问并出席纪念苏联伟大卫国战争胜利80周年庆典