MyBatis验证多级缓存及 Cache Aside 模式的应用小结

 更新时间:2024年12月05日 11:20:00   作者:Ch.yang  
本文介绍了MyBatis的多级缓存机制,包括本地缓存和全局缓存,并通过Spock测试框架验证了多级缓存的实现,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧

前言

MyBatis 官方文档 中文版本没有翻译cache的部分,网上资料比较杂。
这里使用 Spock 测试框架验证下多级缓存,并探索 Mybatis 的 CacheAside 模式。注意:

  • 本文用 本地缓存 表示一级缓存,全局缓存 表示二级缓存
  • 用例仓库

1. 多级缓存的概念

多级缓存可以联系CPU的结构,离核心约近的一致性越高。

1.1 CPU 多级缓存

1.2 MyBatis 多级缓存

本地缓存默认开启,全局缓存需要使用 <cache/> 开启

By default, just local session caching is enabled that is used solely to cache data for the duration of a session. To enable a global second level of caching you simply need to add one line to your SQL Mapping file:

<mapper namespace="com.james.mapper.FileCacheMapper">
    <cache/> <!-- 声明该标签,全局缓存开启 -->
    <select id="select" resultType="java.lang.String">
        SELECT file_name FROM file
    </select>
</mapper>

2. MyBatis 本地缓存

用 Spring 注入的 mapper,调用一次select方法就会产生一个 sqlSession,没有利用到本地缓存。

    def "未使用事务,第二次查询,不命中本地缓存"() {
        given:
        def list1 = mapper.select()
        def list2 = mapper.select()
        expect:
        list1 !== list2
    }

用事务包裹后,两次 select 共用一个 sqlSession,缓存命中

 	def "使用事务,命中缓存"() {
        given:
        def list1 = []
        def list2 = []
        when:
        transaction.execute {
            list1 = mapper.select()
            list2 = mapper.select()
        }
        then:
        // 同一个事务使用同一个SqlSession,若引用相同则认为命中缓存
        list1 === list2
    }

note: groovy 中 list1 === list2 表示引用相同,list1 == list2 表示两个列表的内容相同

3. MyBatis 全局缓存

上文说到,没有事务保护的 select方法调用无法公用一个 sqlSession,所以利用不了本地缓存。
全局缓存的范围更大,只要是同一个mapper的调用,都会被缓存。

    def "全局缓存默认关闭,需要在xml文件中使用 <cache/> 标签启用"() {
        given:
        def list1  = fileCacheMapper.select()
        def list2  = fileCacheMapper.select()
        expect:
        // 由于 SerializedCache.java:64 使用的是由byte[]序列化方式存储元素,所以实例的地址必然不同
        list1 !== list2
        list1 == list2
    }

3.1 MyBatis 全局缓存过期算法

值得关注的是 SOFT 和 WEAK 的类型,对应Java中软引用和弱引用。
软引用是在内存不足时GC可以回收,弱引用是下次GC即可回收(比软引用)积极。

3.2 CacheAside 模式

以下是 Mybatis 默认的全局缓存失效模式,也就是 Cache Aside 模式的应用。

  • 查询的时候,如果没有缓存,则写入。
  • 任何数据操作,使缓存失效。
<select ... flushCache="false" useCache="true"/>
<insert ... flushCache="true"/>
<update ... flushCache="true"/>
<delete ... flushCache="true"/>

后记

Cache Aside 并不能保证强一致性,不然也就不会有 Paxos 这种复杂的共识算法了。 —— 《凤凰架构》

MyBatis 提供了缓存切口, 采用 Redis 会引入什么问题?

  • 多实例之间缓存重复的失效问题,查询时竞争写缓存的问题。
  • ORM框架与中间件耦合,违反单一职责。

万一遇到需强一致场景,如何增强?

两个查询请求同时到来,此时缓存为空,需要将MySql数据写入缓存。此时会出现竞争写缓存的情况。用写锁来保证缓存内的数据跟数据库保持一致。

public void query() {
	if (cache 命中) {
		retrun cache
	} 
	获取缓存写锁
	if (获取锁失败) {
		return 查数据库
	} 
	查数据库
	写缓存
	释放缓存写锁
}

到此这篇关于MyBatis验证多级缓存及 Cache Aside 模式的应用小结的文章就介绍到这了,更多相关MyBatis验证多级缓存内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java使用Zxing二维码生成的简单示例

    Java使用Zxing二维码生成的简单示例

    ZXing是一个开源的,用Java实现的多种格式的1D/2D条码图像处理库,下面这篇文章主要给大家介绍了关于Java使用Zxing二维码生成的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2023-01-01
  • jmeter的时间戳函数使用

    jmeter的时间戳函数使用

    在使用jmeter做接口测试的时候,经常会要用到日期这种函数,本文主要介绍了jmeter的时间戳函数使用,感兴趣的可以了解一下
    2021-11-11
  • Java Calendar类常用示例_动力节点Java学院整理

    Java Calendar类常用示例_动力节点Java学院整理

    从JDK1.1版本开始,在处理日期和时间时,系统推荐使用Calendar类进行实现。接下来通过实例代码给大家详细介绍Java Calendar类相关知识,需要的朋友参考下吧
    2017-04-04
  • Java并发容器相关知识总结

    Java并发容器相关知识总结

    今天给大家带来的文章是Java并发容器的相关知识,文中有非常详细的介绍,对正在学习Java并发容器的小伙伴们很有帮助,需要的朋友可以参考下
    2021-06-06
  • Java中JSONObject和Map<String, Object>的转换方法

    Java中JSONObject和Map<String, Object>的转换方法

    平时对接口时,经常遇到json字符串和map对象之间的交互,这篇文章主要给大家介绍了关于Java中JSONObject和Map<String, Object>的转换方法,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-07-07
  • 使用Java反射获取方法的全路径名称的步骤

    使用Java反射获取方法的全路径名称的步骤

    Java反射是一个强大的特性,它允许程序在运行时查询和修改类的行为,反射可以用于实现很多高级功能,比如动态代理、依赖注入等,本文将介绍如何使用Java反射来实现这一功能,需要的朋友可以参考下
    2024-07-07
  • Spring实现Logback日志模板设置动态参数功能

    Spring实现Logback日志模板设置动态参数功能

    本文介绍如何在Spring应用中实现Logback日志模板的动态参数设置,通过设计traceId链路标识,将其动态添加到日志输出中,从而实现简易的链路追踪功能,感兴趣的朋友跟随小编一起看看吧
    2024-11-11
  • Springmvc conver实现原理及用法解析

    Springmvc conver实现原理及用法解析

    这篇文章主要介绍了Springmvc conver实现原理及用法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • java判断字符串中是否包含中文并过滤中文

    java判断字符串中是否包含中文并过滤中文

    这篇文章主要为大家详细介绍了java判断字符串中是否包含中文,并过滤掉中文,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-09-09
  • hadoop是什么语言

    hadoop是什么语言

    Hadoop是一个由Apache基金会所开发的分布式系统基础架构。 用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储
    2017-09-09

最新评论