当前位置: 首页 > article >正文

大厂面试真题-说一下Mybatis的缓存

首先看一下原理图

Mybatis提供了两种缓存机制:一级缓存(L1 Cache)和二级缓存(L2 Cache),旨在提高数据库查询的性能,减少数据库的访问次数。注意查询的顺序是先二级缓存,再一级缓存。

相关配置

映射文件中的开关(二级缓存的)

一级缓存(L1 Cache)

实现原理

一级缓存是SqlSession级别的缓存,它基于PerpetualCache类实现,该类是Mybatis默认的缓存实现,内部使用HashMap来存储缓存数据。每个SqlSession在创建时都会关联一个Executor,Executor中包含了两个重要的缓存对象:localCachelocalOutputParameterCache(后者主要用于存储过程调用,此处主要讨论localCache)。

BaseExecutor类中,localCache被初始化为PerpetualCache的实例,并存储在Executor对象中。当执行查询操作时,Mybatis会首先检查localCache中是否存在相同的查询(通过CacheKey来唯一标识一个查询),如果存在,则直接从缓存中返回结果;如果不存在,则执行数据库查询,将结果放入localCache中,并返回给调用者。

BaseExecutor类中,可以看到localCache的声明和初始化:

protected PerpetualCache localCache;  
  
protected BaseExecutor(Configuration configuration, Transaction transaction) {  
    // ... 其他初始化代码  
    this.localCache = new PerpetualCache("LocalCache");  
    // ... 其他初始化代码  
}

PerpetualCache类实现了Cache接口,其内部使用HashMap来存储缓存数据:

Executor

概述

Executor是Mybatis中的一个核心接口,它定义了数据库操作的基本方法,如查询(query)、更新(update)、提交(commit)、回滚(rollback)以及清空缓存(clearCache)等。Executor接口的实现类负责具体的SQL执行和缓存管理逻辑。

实现类

  • BaseExecutor:这是一个抽象类,实现了Executor接口的大部分方法,并为子类提供了缓存管理和事务管理的基本功能。子类需要实现doUpdatedoQuerydoQueryCursordoFlushStatements等四个基本方法来完成数据库的相关操作。
  • SimpleExecutor:这是BaseExecutor的一个子类,实现了最基础的SQL执行逻辑,每次执行SQL时都会创建一个新的Statement对象,并不涉及复杂的缓存机制。它是Mybatis的默认执行器。
  • ReuseExecutor:这个执行器实现了Statement的重用功能,它通过内部缓存机制,在同一个SqlSession范围内重用相同的Statement对象,以减少SQL预编译的开销。
  • BatchExecutor:顾名思义,这个执行器用于执行批量操作,它将多个SQL语句打包发送到数据库执行,以减少网络开销和提高性能。
特点与生效条件
  • 作用域:一级缓存是SqlSession级别的缓存,缓存的数据只在当前SqlSession内有效。
  • 默认状态:Mybatis默认开启一级缓存。
  • 生效条件:同一个SqlSession中执行相同的SQL查询时,第一次查询会查询数据库,并将结果存储在缓存中;后续的相同查询则直接从缓存中获取数据,不再访问数据库。
  • 失效条件
    1. 使用不同的SqlSession。
    2. 在同一个SqlSession中,两次查询之间执行了增删改操作(insert、update、delete),这些操作会清空SqlSession中的缓存。
    3. 手动清空了缓存。
    4. 两次查询的查询条件不一致。
应用场景

一级缓存适用于单个SqlSession中的多次相同查询场景,可以有效减少数据库的访问次数,提高查询效率。然而,由于其作用域限制,它不适用于跨SqlSession的查询优化。

二级缓存(L2 Cache)

实现原理

二级缓存是Mapper级别的缓存,它允许多个SqlSession共享缓存数据。二级缓存的开启需要在全局配置文件和Mapper XML文件中进行设置。在Mybatis中,二级缓存是通过Cache接口的实现类来管理的,但Mybatis默认提供了PerpetualCache作为二级缓存的实现。

当二级缓存开启后,Mybatis会为每个Mapper的namespace创建一个独立的缓存区域。当执行查询时,Mybatis会首先检查该Mapper的二级缓存中是否存在相同的查询结果;如果存在,则直接返回缓存中的数据;如果不存在,则执行数据库查询,将结果放入二级缓存中,并返回给调用者。

CachingExecutor

概述

CachingExecutorExecutor的一个实现类,它通过包装其他Executor实现类(如SimpleExecutorReuseExecutorBatchExecutor,这里使用的是装饰器模式),实现了二级缓存机制。它首先检查缓存中是否存在相同查询的结果,如果存在则直接返回缓存中的结果,否则通过被包装的Executor执行查询操作,并将结果存入缓存。

实现步骤

  • 缓存检查:在执行查询操作之前,CachingExecutor会首先检查其管理的二级缓存中是否存在相同查询的结果。这通常通过比较查询的CacheKey来实现,CacheKey是根据查询的SQL语句、参数等信息生成的唯一标识符。
  • 执行查询:如果缓存中不存在相同查询的结果,CachingExecutor会委托给被包装的Executor执行查询操作,并获取查询结果。
  • 缓存结果:将查询结果存入二级缓存中,以便后续相同的查询能够直接从缓存中获取结果。
  • 缓存管理CachingExecutor还负责缓存的清空、提交和回滚等操作,以确保数据的一致性和缓存的有效性。
特点与生效条件
  • 作用域:二级缓存是Mapper级别的缓存,同一个namespace下的所有SqlSession共享这个缓存。
  • 默认状态:Mybatis默认关闭二级缓存,需要手动开启。
  • 开启条件
    1. 在mapper.xml文件中设置<cache/>标签。
    2. 查询数据所转换的实体类类型必须实现序列化接口。
    3. 必须在SqlSession关闭或提交后,才会开启二级缓存。
  • 失效条件
    1. 同一个namespace下的增删改操作会清空缓存。
    2. 缓存超时设置(如果有的话)。
    3. 手动清空缓存。
应用场景
  1. 查询频率高且数据不经常变动的场景:当一个查询被频繁执行,且查询结果很少发生改变时,可以将查询结果缓存在二级缓存中,以提高查询性能。
  2. 多个会话共享相同数据的场景:当多个SqlSession需要共享相同的数据时,可以使用二级缓存来避免重复的数据库查询操作,提高系统性能。
  3. 减轻数据库的负载:在高并发的情况下,数据库可能会成为系统的瓶颈。通过使用二级缓存,可以减轻数据库的负载,提高系统的并发处理能力。


http://www.kler.cn/a/324339.html

相关文章:

  • Spark 之 Cache
  • 《操作系统 - 清华大学》3 -3:连续内存分配:内存碎片与分区的动态分配
  • ElasticSearch学习笔记二:使用Java客户端
  • MySQL技巧之跨服务器数据查询:基础篇-A数据库与B数据库查询合并
  • leetcode 扫描线专题 06-leetcode.253 meeting room ii 力扣.253 会议室 II
  • 【机器学习导引】ch6-支持向量机
  • 【分布式微服务云原生】详细介绍下dubbo和springcloud所能支持的微服务特性,为啥能支持的技术原理,以及适用的业务场景,并对两者各方面做个详细的比较
  • Qt/C++ 解决调用国密SM3,SM4加密解密字符串HEX,BASE64格式转换和PKCS5Padding字符串填充相关问题
  • Java线程基础
  • SQL CREATE TABLE 语句
  • TypeScript概念讲解
  • DePIN 代表项目 CESS 受邀出席国会山活动,向议员展示创新 DePIN 技术
  • 阿里rtc云端录制TypeScript版NODE运行
  • HarmonyOS安全能力介绍
  • 240927-各种卷积最清晰易懂blender动画展示
  • Spark 的 Skew Join 详解
  • Spring Boot 2.4.3 + Java 8 升级为 Java 21 + Spring Boot 3.2.0
  • ubuntu 不用每次输入sudo的四种方式
  • 基于python+django+vue的电影数据分析及可视化系统
  • 滚雪球学MySQL[6.1讲]:数据备份与恢复
  • 初始MYSQL数据库(6)—— 事务
  • 什么东西可以当做GC Root,跨代引用如何处理?
  • 【LLM】从零预训练一个tiny-llama
  • python高级用法_装饰器
  • text2sql方法:NatSQL和DIN-SQL
  • 【Redis 源码】4adlist列表.md