MyBatis 的多级缓存机制是怎么样运作的?

引言:上周三,小 X 去面试一家中厂,其中面试官问到 MyBatis 的多级缓存机制是怎么样运行的?这个问题可以好好准备一下,很多人可能只会用 MyBatisPlus,简单的多表联查 SQL 语句可能都写不出来,更别说索引优化、SQL 语句优化、安全漏洞等问题了,先打好基础,才能更好地学习。

题目

MyBatis 的多级缓存机制是怎么样运作的?

推荐解析

一级缓存

1)MyBatis 的一级缓存默认开启,且默认作用范围为 SESSION,即一级缓存在一个会话中生效,也可以通过配置将作用范围设置为 STATEMENT,让一级缓存仅针对当前执行的 SQL 语句生效。
2)在同一个会话中,执行增,删,改操作会使本会话中的一级缓存失效。
3)不同会话持有不同的一级缓存,本会话内的操作不会影响其它会话内的一级缓存。

Session 针对浏览器会话,不同会话的同一个 SQL 语句,自然是不会走一级缓存。同一个浏览器会话,但是查询条件不同,比如 Where 条件不同,依然不会走一级缓存,或者同一个浏览器在两个相同的查询条件下,中间执行了一次增、删、改的操作,一级缓存依然失效。

**特别注意:**一级缓存针对的范围是什么?以及一级缓存失效的场景,当然一般我们都会在 yml 配置中去开启日志,通过查看日志可以看到缓存是否被使用!

二级缓存

1) MyBatis 中的二级缓存默认开启,可以在 MyBatis 配置文件中的<settings>中添加<setting name="cacheEnabled" value="false"/>将二级缓存关闭;
2)MyBatis 中的二级缓存作用范围是同一命名空间下的多个会话共享,这里的命名空间就是映射文件的 namespace,即不同会话使用同一映射文件中的 SQL 语句对数据库执行操作并提交事务后,均会影响这个映射文件持有的二级缓存;
3)MyBatis 中执行查询操作后,需要提交事务才能将查询结果缓存到二级缓存中;
4)MyBatis 中执行增,删或改操作并提交事务后,会清空对应的二级缓存;
5)MyBatis 中需要在映射文件中添加<cache>标签来为映射文件配置二级缓存,也可以在映射文件中添加<cache-ref>标签来引用其它映射文件的二级缓存以达到多个映射文件持有同一份二级缓存的效果。

二级缓存配置项

在 Mapper 配置文件中添加的 Cache 标签中可以设置相关属性。

1)Eviction 属性:缓存回收策略(LRU、FIFO、SOFT、WEAK)

2)FlushInterval属性:刷新间隔,单位毫秒,默认没有刷新间隔,语句被调用时缓存会刷新。

3)Size:引用的数目,缓存存储的对象数量,考虑到内存溢出问题。

4)ReadOnly:只读,是否是只读缓存,如果为 true,所有调用者返回缓存对象的相同实例。如果为 false,会返回缓存对象的拷贝(序列化对象),性能慢,但安全性高,默认为 false。

是否需要三级缓存?

概念:三级缓存通常指的是在分布式系统中,跨应用实例的缓存层,如使用 Redis 或 Memcached 作为缓存存储。

作用:三级缓存可以进一步减少对数据库的访问,提高系统的扩展性和性能。

考虑因素:是否需要三级缓存取决于应用的规模、架构和性能需求。如果应用部署在多个服务器上,且需要共享数据,可能需要考虑引入三级缓存。

实现:三级缓存通常不是由 MyBatis 直接提供,而是通过集成外部缓存系统来实现。

应用规模:对于大型应用或分布式系统,三级缓存可以提供更好的性能和扩展性。

性能需求:如果应用对性能有较高要求,尤其是在高并发场景下,三级缓存可以显著减少数据库的压力。

数据一致性:引入三级缓存需要考虑数据一致性问题,确保缓存与数据库之间的数据同步。

复杂性:实现三级缓存可能会增加系统的复杂性,需要权衡实现成本和性能收益。

其他补充

鱼聪明 AI 的回答:

鱼聪明 AI 地址:https://www.yucongming.com/

一级缓存示例:

一级缓存是自动启用的,不需要额外配置。它通常在 SqlSession 的生命周期内有效。

// 获取 SqlSession
SqlSession session = sqlSessionFactory.openSession();try {// 查询用户,一级缓存会自动存储这个查询结果User user1 = session.selectOne("com.example.mapper.User.selectById", 1L);// 再次查询相同的用户,这次将从一级缓存中获取结果User user2 = session.selectOne("com.example.mapper.User.selectById", 1L);// 检验缓存是否失效:在一级缓存中,可以通过比较 user1 和 user2 是否相同来检验if (user1 == user2) {System.out.println("一级缓存有效");} else {System.out.println("一级缓存失效");}} finally {session.close(); // 关闭 SqlSession,结束一级缓存的生命周期
}

二级缓存示例:

二级缓存需要在 MyBatis 配置文件中配置,并在 Mapper 接口上使用 @CacheNamespace 注解。

<!-- mybatis-config.xml -->
<configuration><settings><!-- 启用二级缓存 --><setting name="cacheEnabled" value="true"/></settings><!-- 配置二级缓存的类型,这里使用 MyBatis 内置的 PerpetualCache --><cache type="org.apache.ibatis.cache.impl.PerpetualCache"><!-- 二级缓存的大小限制 --><property name="size" value="1024"/></cache>
</configuration>
// 在 Mapper 接口上使用 @CacheNamespace 注解
@CacheNamespace
public interface UserMapper {User selectById(Long id);
}
// 使用二级缓存的示例
SqlSession session = sqlSessionFactory.openSession();try {// 查询用户,结果将被存储在二级缓存中User user1 = session.getMapper(UserMapper.class).selectById(1L);// 关闭当前会话,然后重新打开一个新的会话session.close();session = sqlSessionFactory.openSession();// 在新的会话中再次查询相同的用户,这次将从二级缓存中获取结果User user2 = session.getMapper(UserMapper.class).selectById(1L);// 检验缓存是否失效:在二级缓存中,可以通过比较 user1 和 user2 是否相同来检验if (user1 == user2) {System.out.println("二级缓存有效");} else {System.out.println("二级缓存失效");}} finally {session.close(); // 关闭 SqlSession
}

检验缓存是否失效:

  • 一级缓存:由于一级缓存仅在 SqlSession 的生命周期内有效,通常不需要手动检验缓存是否失效。当 SqlSession 关闭时,一级缓存自动失效。
  • 二级缓存:可以通过比较两次查询返回的对象引用是否相同来检验缓存是否失效。如果相同,说明缓存有效;如果不同,说明缓存可能已经失效。

欢迎交流

本文主要介绍 MyBatis 的一二级缓存和缓存失效的主要场景,以及是否需要三级缓存的问题,关于数据库方面是一个重点项,因为不同语言都需要利用数据库进行持久化存储,无论哪种 ORM 框架都有各自的优缺点,需要根据实际场景进行选择,在文末还有三个提问,欢迎小伙伴在评论区进行留言!近期面试鸭小程序已全面上线,想要刷题的小伙伴可以积极参与!

1)一级缓存和二级缓存的区别是什么?

2)如何配置和管理二级缓存?

3)MyBatis的一级缓存是如何工作的?它的生命周期是什么时候开始和结束的?什么情况下会导致一级缓存的失效或刷新?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/28221.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python 项目应该放弃requirements.txt?揭秘PDM的强大功能

目录 requirements.txt的局限性 PDM 的优势 如何使用 PDM 安装 PDM 初始化项目 添加依赖 管理依赖 示例代码 初始化项目并添加依赖 编写简单的 Flask 应用 运行应用 PDM高级功能 多环境管理 脚本管理 发布包 在 Python 项目中管理依赖项&#xff0c;最常见的方式…

Android APP memory统计方法

目录 进程的内存信息概述 关键的术语 测试步骤 测试步骤 数据处理 数据分析&#xff1a; 进程内存信息 Dumpsys meminfo -a PID Procrank Procmem PID 特殊内存信息 Mali ION(multi-media&#xff0c;gralloc) 进程地址空间信息 /proc/pid/smaps Showmap PID …

随笔-来了,安了

依照领导定的规矩&#xff0c;周五又去了分公司&#xff0c;赋能一线去了。到了地方就是开会->现场解决问题->干饭->开会过需求、提供解决方案&#xff0c;充实得厉害。强度也不小&#xff0c;中午干的一大碗饭&#xff0c;到五点就饿了。 六点带着分公司催着上线的需…

5000天后的世界

为何可以预见未来 1993年&#xff0c;在互联网的黎明时代&#xff0c;凯文凯利创办了《连线》杂志。他曾经采访过以比尔盖茨、史蒂夫乔布斯、杰夫贝佐斯为代表的一众风云创业家。《连线》杂志是全球发行的世界著名杂志&#xff0c;一直致力于报道科学技术带来的经济、社会变革…

【0基础学爬虫】爬虫基础之自动化工具 DrissionPage 的使用

概述 前三期文章中已经介绍到了 Selenium 与 Playwright 、Pyppeteer 的使用方法&#xff0c;它们的功能都非常强大。而本期要讲的 DrissionPage 更为独特&#xff0c;强大&#xff0c;而且使用更为方便&#xff0c;目前检测少&#xff0c;强烈推荐&#xff01;&#xff01;&a…

Google Earth Engine(GEE)——计算闪闪红星的ndvi的值和折线图(时序分析)

函数: ui.Chart.image.doySeries(imageCollection, region, regionReducer, scale, yearReducer, startDay, endDay)

手把手教你改造Sentinel Dashboard 实现配置持久化

一. 概述 Sentinel客户端默认情况下接收到 Dashboard 推送的规则配置后&#xff0c;可以实时生效。但是有一个致命缺陷&#xff0c;Dashboard和业务服务并没有持久化这些配置&#xff0c;当业务服务重启后&#xff0c;这些规则配置将全部丢失。 Sentinel 提供两种方式修改规则…

政务云参考技术架构

行业优势 总体架构 政务云平台技术框架图&#xff0c;由机房环境、基础设施层、支撑软件层及业务应用层组成&#xff0c;在运维、安全和运营体系的保障下&#xff0c;为政务云使用单位提供统一服务支撑。 功能架构 标准双区隔离 参照国家电子政务规范&#xff0c;打造符合标准的…

B3981 [信息与未来 2024] 图灵完备

题目描述 &#xff08;你不需要看懂这张图片&#xff1b;但如果你看懂了&#xff0c;会觉得它很有趣。&#xff09; JavaScript 是一种功能强大且灵活的编程语言&#xff0c;也是现代 Web 开发的三大支柱之一 (另外两个是 HTML 和 CSS)。灵活的 JavaScript 包含“自动类型转换…

从数据库到数据仓库:数据仓库导论

导言 本文为数据仓库导论&#xff0c;旨在介绍数据仓库的基本理念和应用场景&#xff0c;帮助读者理解数据仓库的重要性及其在企业中的实际应用。 数据仓库作为重要的数据管理和分析工具&#xff0c;已经发展了30多年&#xff0c;其过程中生态和技术都发生了巨大的变化。尽管…

分布式数据库核心问题和解决方法

当下&#xff0c;由于成本压力以及数据保护的要求&#xff0c;采用国产数据库的呼声越来越高&#xff0c;但是国产数据库数量众多&#xff0c;良莠不齐&#xff0c;没有选择数据库比较靠谱的标准&#xff0c;业内真正懂得数据库的人很少&#xff0c;且为了这块大的蛋糕&#xf…

Axios进阶

目录 axios实例 axios请求配置 拦截器 请求拦截器 响应拦截器 取消请求 axios不仅仅是简单的用基础请求用法的形式向服务器请求数据&#xff0c;一旦请求的端口与次数变多之后&#xff0c;简单的请求用法会有些许麻烦。所以&#xff0c;axios允许我们进行创建axios实例、ax…

Retrofit 注解参数详解

添加依赖 implementation com.squareup.retrofit2:retrofit:2.9.0 implementation com.squareup.retrofit2:converter-gson:2.9.0 初始化Retrofit val retrofit Retrofit.Builder().baseUrl("http://api.github.com/").addConverterFactory(GsonConverterFactory…

【Kafka】Kafka提高生产者吞吐量、数据可靠性-06

【Kafka】Kafka提高生产者吞吐量-06 1. 提高生产者吞吐量2.数据可靠性2.1 回顾数据的发送流程2.2 ack应答级别2.2.1 acks:02.2.2 acks:12.2.2 acks:-1(all)2.2.2.1 数据可靠性分析2.2.2.2 数据完全可靠 2.3 可靠性总结2.4 可靠性代码配置 1. 提高生产者吞吐量 import org.apach…

科技云报道:“元年”之后,生成式AI将走向何方?

科技云报道原创。 近两年&#xff0c;以大模型为代表的生成式AI技术&#xff0c;成为引爆数字原生最重要的技术奇点&#xff0c;人们见证了各类文生应用的进展速度。Gartner预测&#xff0c;到2026年&#xff0c;超过80%的企业将使用生成式AI的API或模型&#xff0c;或在生产环…

「实战应用」如何用图表控件LightningChart JS创建SQL仪表板应用(二)

LightningChart JS是Web上性能特高的图表库&#xff0c;具有出色的执行性能 - 使用高数据速率同时监控数十个数据源。 GPU加速和WebGL渲染确保您的设备的图形处理器得到有效利用&#xff0c;从而实现高刷新率和流畅的动画&#xff0c;常用于贸易&#xff0c;工程&#xff0c;航…

OpenCore 引导完美升级

备份原有 OC (做好回滚的准备下载新版 OpenCore https://github.com/acidanthera/OpenCorePkg/releases将 1, 3, 4 里面的文件使用新版进行替换 4 里面的文件严格来说并不需要, 只是留着方便使用不追求完美到这就可以收工了将 OC 复制到 U 盘 EFI U 盘格式化可以使用: diskutil…

微服务开发与实战Day09 - Elasticsearch

一、DSL查询 Elasticsearch提供了DSL&#xff08;Domain Specific Language&#xff09;查询&#xff0c;就是以JSON格式来定义查询条件。类似这样&#xff1a; DSL查询可以分为两大类&#xff1a; 叶子查询&#xff08;Leaf query clauses&#xff09;&#xff1a;一般是在特…

Docker Jenkins(改错版本)

Devops:它强调开发(Development)和运维(Operations)团队之间的协作.实现更快,更可靠的软件交付部署. JenKins是一个开源的自动化服务器,广泛用于构建,测试和部署软件项目.它是持续集成(CI)和持续交付/部署(CD)的工具.JenKins是实现DevOps实践的重要工具. 前端项目部署一般流程:…

Matlab|基于V图的配电网电动汽车充电站选址定容-可视化

1主要内容 基于粒子群算法的电动汽车充电站和光伏最优选址和定容 关键词&#xff1a;选址定容 电动汽车 充电站位置 仿真平台&#xff1a;MATLAB 主要内容&#xff1a;代码主要做的是一个电动汽车充电站和分布式光伏的选址定容问题&#xff0c;提出了能够计及地理因素和服…