写在最前
本文章对mybatis缓存整体进行浅析,但并不是深究其实现原理,而是对mybatis缓存框架的基本认知,对我们选择缓存框架时有一定的帮助
mybatis缓存结构
- mybatis的查询缓存分为一级缓存和二级缓存
- 一级缓存是SqlSession级别的缓存,二级缓存时mapper级别的缓存
- 查询执行顺序: 是否开启查询二级缓存 -> 是否开启查询一级缓存 -> 查询数据库
- 若开启了二级缓存其数据是由一级缓存获取,若一级缓存关闭了则二级缓存也不会有数据
- 一级缓存默认开启,二级缓存默认关闭
一级缓存
- Mybatis默认开启一级缓存,生命周期为sqlsession内
- 在sqlSession对象持有一个(内存区域)数据结构(HashMap)用于存储缓存数据
- 不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的
- 用户不能配置
二级缓存
- Mybatis默认关闭二级缓存
- 作用域是mapper的同一个namespace,即application域
- 当同一个namespace进行插入更新删除操作时会清空该namespace的所有缓存
- 注意事项:
- 往往操作同一张表但不在同一个Mapper里,则二级缓存将会存在**脏读**。
- 在mapper中存在多表连接查询时,所涉及的表可能不在同一个mapper中,则导致表的insert,update,delete不能更新多表连接的mapper缓存
开启二级缓存
- 0.配置pom.xml
<!-- spring boot mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
-
- 开启mybatis全局缓存支持(二级缓存):mybatis-config.xml [spring boot忽略此步骤]
<settings>
<!-- 该属性默认为false -->
<setting name="cacheEnabled" value="true"/>
</settings>
- 2.Mapper配置文件添加cache标签(*Mapper.xml)
<!-- mybatis 二级缓存 属性配置:
eviction : 缓存的回收策略:LRU,FIFO,SOFT,WEAK, 默认的是 LRU
flushInterval : 缓存清空刷新间隔(ms),默认不清空
readOnly : 是否只读
• true – 只读:返回缓存对象的引用;速度快,但不安全。
• false – 非只读:利用序列化&反序列技术克隆一份新的数据给用户; 安全,但速度慢。
size : 缓存最多可以存放多少对象,太大容易导致内存溢出。
type : 指定自定义缓存的全类名;需实现Cache接口;
-->
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
spring boot 使用ehcache二级缓存
-
- pom.xml引入ehcache
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<!-- Mybatis 二级缓存 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.0.0</version>
</dependency>
-
- 可选配置classpath:ehcache.xml,不配置ehcache默认读取ehcache.jar中的ehcache-failsafe.xml
- spring boot在application.properties中可以指定ehcache文件:
spring.cache.ehcache.config=classpath:cus-ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<!--
缓存配置
diskStore:指定数据在磁盘中的存储位置。
name:缓存名称。
defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略,以下属性是必须的:
maxElementsInMemory:缓存最大个数。
eternal:对象是否永久有效,一但设置了,timeout将不起作用。
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
maxElementsOnDisk:硬盘最大缓存个数。
diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。
-->
<diskStore path="java.io.tmpdir"/>
<!-- 设定缓存的默认数据过期策略 -->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
</ehcache>
- 2.Mapper文件配置cache
<!--mybatis ehcache缓存配置 -->
<!-- 以下两个<cache>标签二选一,第一个可以输出日志,第二个不输出日志 -->
<!--<cache type="org.mybatis.caches.ehcache.LoggingEhcache" />-->
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
写在最后
- 缓存回收算法:
- LRU – 最近最少使用的:移除最长时间不被使用的对象。
- FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
- SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
- WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。