当前位置: 代码网 > it编程>编程语言>Java > MyBatis验证多级缓存及 Cache Aside 模式的应用小结

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

2024年12月06日 Java 我要评论
前言mybatis 官方文档 中文版本没有翻译cache的部分,网上资料比较杂。这里使用 spock 测试框架验证下多级缓存,并探索 mybatis 的 cacheaside 模式。注意:本文用 本地

前言

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验证多级缓存内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com