美文网首页JavaJava 程序员
Mybatis 二级缓存的介绍及使用,使用redis实现二级缓存

Mybatis 二级缓存的介绍及使用,使用redis实现二级缓存

作者: 马小莫QAQ | 来源:发表于2022-04-20 22:26 被阅读0次

    一、二级缓存

    二级缓存是全局作用域缓存,默认是不开启的,需要手动进行配置。

    Mybatis提供二级缓存的接口以及实现,缓存实现的时候要求实体类实现Serializable接口,二级缓存在sqlSession关闭或提交之后才会生效。

    1-1、特性:

    • 默认已经开启,但是未实现
    • 作用域:基于全局范围应用级别
    • 缓存默认同样使用一级缓存的PerpetualCache类,不同的是在这个基础之上又套了一层Map(org.apache.ibatis.session.Configuration#caches ),其key为Mapper的namespace,value则为PerpetualCache中的Map.
    • 事务提交的时候(sqlSession关闭)进行缓存存储。

    1-2、实现:

    • 开启二级缓存的配置
    <!--全局性开启或者关闭已在PojoMapper中配置的任何缓存,默认为true-->
    <setting name="cacheEnabled" value="true"/>
    
    • 在需要用到二级缓存的文件中假如,基于Mapper映射文件来实现缓存,基于Mapper的namespace来存储的。
    • 在需要使用到二级缓存的javaBean,需要实现序列化接口 Serializable
    • 查询的时候先从二级缓冲中查询,如果二级缓存中没查询到,再从一级缓存中查询

    1-3、失效

    • 同一个命名空间,进行了增删改操作,缓存就会失效

    二、Mybatis的实现

    2-1、在DeptMapper.xml中添加cache标签

    2-2、给Dept实现序列化接口

    2-3、测试

    2-3-1、同一个sqlSession实现二级缓存

    如下,在第一次执行之后,需要先对sqlSession进行提交,这样才会把第一次的数据存储到二级缓存中,然后第二次查询的时候就会去二级缓存中查询。 [图片上传失败...(image-413dd0-1650464370190)]

    2-3-2、不同的sqlSession实现二级缓存

    如下,第一个sqlSession关闭之后,第二个sqlSession在查询的时候就会命中二级缓存 [图片上传失败...(image-4750c3-1650464370190)]

    2-3-3、二级缓存命中率

    通过上面的测试,可以看到查询二级缓存都有有一个命中率。
    命中率的计算=总命中次数/总查询次数

    2-4、实现增删改不删除二级缓存

    上面提到,同一个命名空间如果执行了增删改就会清除当前命名空间的缓存,实际上也可以通过配置,即使执行了增删改操作,也可以不删除缓存。

    2-4-1、实现删除缓存操作
    2-4-1-1、DeptMapper.xml中添加更新方法
    2-4-1-2、编写测试方法

    如下:
    第一次为查询操作,并且关闭数sqlSession.
    第二次为更新操作,提交事务,关闭sqlSession.
    第三次为查询操作,因为有了第二次更新操作,缓存清除,就无法命中缓存了。

    2-4-1-3、测试

    如下可以看到第三次查询的命中率为0。 [图片上传失败...(image-a5d719-1650464370190)]

    2-4-2、实现增删改不删除缓存操作
    2-4-2-1、给DeptMapper.xml方法添加flushCache="false"
    2-4-2-2、测试

    如下,通过给修改方法添加了flushCache=false,缓存就不会被清除了。 [图片上传失败...(image-7c3d7a-1650464370190)]

    2-4-3、增删改不清除缓存的隐患

    假如在增删改的情况下不清除缓存,就可能产生脏读的可能,举例如下:
    第一次查询所有的部门列表,结果为10条。
    第二次删除其中其中一条部门,结果为9条。
    第三次查询所有部门列表,从缓存中获取10条。

    这样就产生了脏读的后果,因此在设置flushCache=false的时候,需要根据实际的业务场景慎重选择。

    一般这种情况下可以对一些惰性数据进行这样处理,比如一个周期内数据即使发生微小改动,不影响整体业务,可以设置flushCache=false,然后过了这个周期设置重新查询并缓存数据。

    2-5、设置查询不提交缓存

    假设我们设置了全局缓存,但是在某个Mapper中的某个方法不需要查询之后,存储缓存,我们就需要给这个查询方法设置不设置缓存

    2-5-1、修改Mapper中的查询方法

    我们先复制查询方法,并且给第一个设置useCache=false,这样第一个方法就不会周缓存(put/get)

    2-5-2、测试

    如下可以看到:
    第一次查询没有二级缓存相关的输出,如命中率
    第二次查询虽然和第一次查询的数据条件一致,但是二级缓存的命中率为0,则代表第一次查询之后未进行缓存设置。

    2-6、设置关联缓存

    比如如下场景:
    我们使用一对多查询部门和员工信息,这样在查询部门的时候,因为设置了二级缓存,因此数据就放入到二级缓存中,这时候对员工表信息进行增删改操作,那部门的二级缓存是无法进行自动更新的,因此旧需要在员工Mapper中国设置一个管理缓存,这样在对员工信息进行增删改的时候,部门的信息缓存就会清除。

    设置<cache-ref="命名空间"/>就可以完成设置。

    在未设置的情况下,虽然对员工表信息进行操作了,但是部门表的缓存依然可以命中。

    局限性: 只能设置一个命名空间,无法设置多个,比如多个地方都引用当前Mapper,就无法指定了。

    2-6-1、设置清除设置
    2-6-2、测试

    第三次查询就无法命中缓存了。

    2-7、缓存属性的解析

    一下为缓存可以配置的属性,下面对相关属性进行解析

    <cache
      eviction="FIFO"
      flushInterval="60000"
      size="512"
      readOnly="true"/>
    

    以上配置含义为:这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。

    eviction清除策略:

    • LRU – 最近最少使用:移除最长时间不被使用的对象。
    • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
    • SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。
    • WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。

    默认的清除策略是 LRU。

    flushInterval 属性间隔
    可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。

    size(引用数目)
    可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。

    readOnly(只读)
    可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。

    type(实现类)
    可以设置缓存的实现类,默认的是:org.apache.ibatis.cache.impl.PerpetualCache,如果不修改可以省略,也可以修改实现类,但是同时必须实现Cache。

    2-8、二级缓存弊端:

    当进行关联查询的时候,如果一个Mapper,关联了多个Mapper,无法进行多个Mapper缓存的更新

    三、使用redis实现二级缓存

    3-1、安装redis

    首先安装redis,可以参考之前的文章redis安装

    3-2、使用maven添加mybatis-redis包

    <dependency>
        <groupId>org.mybatis.caches</groupId>
        <artifactId>mybatis-redis</artifactId>
        <version>1.0.0-beta2</version>
    </dependency>
    

    3-3、修改Mapper的cache类型

    添加 maven包之后,可以找到RedisCache类,复制完整限定名

    将完整限定名粘贴到DeptMapper的Cache 中

    3-4、添加redis.properties文件

    在resource下面添加redis.properties配置文件,并添加相关redis配置,如下

    3-5、再次执行测试

    给RedisCache打断点,判断是否走了

    可以看到已经进入断点,key的值如上

    3-6、连接redis工具查看数据

    如上图,可以看到redis中的key为mapper的namespace,值又是一个map,Map中实际又是一级缓存的key和value

    作者:Jony_zhang

    链接:https://juejin.cn/post/7088488932291117069
    来源:稀土掘金

    相关文章

      网友评论

        本文标题:Mybatis 二级缓存的介绍及使用,使用redis实现二级缓存

        本文链接:https://www.haomeiwen.com/subject/xnebertx.html