一文彻底读懂优秀开源产品MyBatis一级缓存设计
孙玄 架构之美
文章插图
- 前言 -
缓存是 MyBatis 中非常重要的特性 。 合理使用缓存能够减少数据库 IO , 显著提升系统性能 。 但是在分布式环境下 , 如果使用不当 , 则可能会带来数据一致性问题 。 MyBatis 提供了一级缓存和二级缓存 , 其中一级缓存基于 SqlSession 实现 , 而二级缓存基于 Mapper , 本文将会详细讲解一级缓存 。
文章插图
- CACHE 缓存 -
MyBatis 跟缓存相关的类都在 Cache 包里面 , 其中有一个 Cache 接口 , 只有一个默认的实现类 PerpetualCache , 它是用 HashMap 实现的 。 除此之外 , 还有很多的装饰器 , 通过这些装饰器可以额外实现很多的功能:回收策略、日志记录、定时刷新等等 。
1、包结构
如图是缓存类所在源码中所处的位置 , 从包名中我们可以知道 decorators 包中存放的是一些装饰类 。
文章插图
2、查看装饰后的结果
但是无论怎么装饰 , 经过多少层装饰 , 最后使用的还是基本的实现类(默认PerpetualCache) 。 我们 debug 看一下经层层装饰后的结果如图:
文章插图
CachingExecutor中Debug查看:缓存的层层装饰
我们后面说的一级缓存缓存就是存放到这个 PerpetualCache 里面 。
3、对装饰器的分类
文章插图
文章插图
- 一级缓存的特点 -
1、一级缓存默认是开启的 , 而且不能关闭
至于一级缓存为什么不能关闭 , MyBatis 核心开发人员做出了解释:
MyBatis的一些关键特性(例如通过和
虽然我们不能关闭一级缓存 , 但是我们可以更改他的作用范围:
MyBatis提供了一个配置参数localCacheScope , 用于控制一级缓存的级别 , 该参数的取值为SESSION、STATEMENT , 当指定localCacheScope参数值为SESSION时 , 缓存对整个SqlSession有效 , 只有执行DML语句(更新语句)时 , 缓存才会被清除 。 当localCacheScope值为STATEMENT时 , 缓存仅对当前执行的语句有效 , 当语句执行完毕后 , 缓存就会被清空 。
能更改一级缓存的作用范围这一点很重要后面我们讲解中会用到这一特性 。
2、一级缓存默认是SqlSession级别的
在操作数据库时需要构造 sqlSession 对象 , 在对象中有一个(内存区域)数据结构(HashMap)用于存储缓存数据 。 不同的 sqlSession 之间的缓存数据区域(HashMap)是互相不影响的 。 用一张图来表示一下一级缓存 , 其中每一个 SqlSession 的内部都会有一个一级缓存对象 。
文章插图
文章插图
- 实验验证一级缓存的作用范围 -
1、一级缓存同一个会话共享数据
模拟思路:打开一个会话 , 进行两次查询通过日志查看第二次是否走数据库 。
代码如下:
@Testpublic void testSession() throws IOException {try (SqlSession sqlSession = sqlSessionFactory.openSession()) {OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);List
日志信息如下:
文章插图
分析:第一次查询打印了 sql 日志信息 , 说明是通过数据库获取到数据 , 第二次也查询到数据但是没有打印日志信息 , 说明走了缓存 。
结论:一级缓存同一个会话共享数据 。
2、同一个会话如果有更新操作则缓存清除
模拟思路:打开一个会话 , 先进行查询 , 然后进行更新操作 , 最后再次查询刚才的语句 , 看是否打印查询数据库的 sql 日志(这些操作都是对一条数据的操作) 。
- 当初|这是我的第一部华为手机,当初花6799元买的,现在“一文不值”?
- 荣耀V30|麒麟990+40W快充,昔日猛将彻底沦为清仓价?网友:太遗憾
- 美国|印度宣布彻底突破5G难关,美英加澳一片欢呼,一周后白宫怒斥被骗
- 大战|一亿像素平民化,Redmi掀起千元机大战,卢伟冰彻底让友商绝望!
- 小米10纪念至尊版|小米彻底疯狂!米10至尊只卖4690!米粉不约吗?
- 流畅|手机里垃圾太多,关闭这个开关,彻底清除垃圾,手机立刻流畅
- 海淘|收到海淘包裹如何降低病毒感染风险?专家回应:手要彻底清洗
- 快充|从小米10 Ultra换成iPhone 12 Pro一周后,我彻底后悔了
- 读懂|一图读懂冷链食品物流防控
- 只需2步,彻底关闭电脑里的弹窗广告,建议收藏