MyBatis 的一级、二级缓存
文章目录
- 1️⃣ 一级缓存(Local Cache)
- 📌 定义
- 🚀 示例代码
- 2️⃣ 二级缓存(Global Cache)
- 📌 定义
- 🚀 使用方式
- 3️⃣ 一级缓存 vs. 二级缓存 📊
- 4️⃣ 数据共享问题
- 🔸 数据一致性问题
- 🔸 并发访问问题
- 🔸 分布式环境中的缓存共享
- 5️⃣ 总结 🚀
MyBatis 提供了强大的缓存机制,以提高数据库查询性能。缓存主要分为 一级缓存 和 二级缓存,它们分别应用于不同的范围和场景。
1️⃣ 一级缓存(Local Cache)
📌 定义
- 作用范围:SqlSession 级别
- 存储位置:SqlSession 内存中
- 默认开启
- 失效条件:
- SqlSession 关闭
- 执行
insert
、update
、delete
操作 - 执行
select
时手动刷新缓存sqlSession.clearCache()
- 查询不同的 SQL 语句
🚀 示例代码
SqlSession sqlSession1 = sqlSessionFactory.openSession();
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
User user1 = mapper1.getUserById(1); // 第一次查询,数据从数据库加载
User user2 = mapper1.getUserById(1); // 第二次查询,数据从缓存获取
sqlSession1.close();
2️⃣ 二级缓存(Global Cache)
📌 定义
- 作用范围:Mapper(Namespace)级别,多 SqlSession 共享
- 存储位置:MyBatis 全局级别缓存,通常存储在
PerpetualCache
- 默认关闭,需要手动开启
- 失效条件:
- 执行
insert
、update
、delete
操作后,缓存会自动清除 - 直接操作数据库
- 执行
🚀 使用方式
- 开启二级缓存(在
mybatis-config.xml
或mapper.xml
中设置):
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
- 在 Mapper 配置中启用缓存
<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
eviction="LRU"
:最近最少使用的缓存清理策略flushInterval="60000"
:60 秒自动刷新缓存size="512"
:最大缓存 512 个对象readOnly="true"
:只读,提高并发效率
- 示例代码
SqlSession sqlSession1 = sqlSessionFactory.openSession();
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
User user1 = mapper1.getUserById(1);
sqlSession1.close(); // 数据写入二级缓存
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
User user2 = mapper2.getUserById(1); // 从二级缓存读取数据
sqlSession2.close();
3️⃣ 一级缓存 vs. 二级缓存 📊
对比项 | 一级缓存 | 二级缓存 |
---|---|---|
作用范围 | SqlSession | Mapper(Namespace)级别,多 SqlSession 共享 |
默认开启 | ✅ 是 | ❌ 否(需手动开启) |
失效条件 | SqlSession 关闭、增删改操作 | 增删改操作、数据库更新、缓存超时 |
适用场景 | 单个会话内查询优化 | 适用于多个 SqlSession 共享数据 |
4️⃣ 数据共享问题
二级缓存的主要作用之一是跨 SqlSession 共享数据,但也会引发一些问题:
🔸 数据一致性问题
- 由于二级缓存存储在 Mapper 级别,数据修改后不会立即更新缓存,可能导致数据不一致。
- 解决方案:
- 使用事务控制,确保数据库更新后及时刷新缓存。
- 定期刷新缓存,通过
flushInterval
机制自动更新。 - 禁用二级缓存,对于高实时性数据建议不使用。
🔸 并发访问问题
- 默认情况下,MyBatis 二级缓存是 readOnly,多个线程访问时不会有并发问题。
- 如果设置
readOnly="false"
,则需要考虑线程安全问题。
🔸 分布式环境中的缓存共享
- 单机应用:二级缓存可以有效减少数据库访问,提高性能。
- 分布式应用:多个服务实例可能无法共享 MyBatis 二级缓存,导致缓存失效或不一致。
- 解决方案:
- 采用 Redis、EhCache 等第三方分布式缓存代替 MyBatis 内置缓存。
- 结合 消息队列(MQ) 机制,在数据更新时广播清除缓存。
5️⃣ 总结 🚀
✅ 一级缓存 适用于 单个 SqlSession,默认开启,生命周期短。
✅ 二级缓存 适用于 多个 SqlSession 共享,默认关闭,需要手动开启。
✅ 数据一致性问题 是二级缓存的关键挑战,需谨慎使用。
✅ 分布式架构下建议使用第三方缓存(如 Redis)以实现缓存共享。
✅ 适用于 读多写少 的场景,如查询热门数据、字典数据等。