介绍一下Mybatis的底层原理(包括一二级缓存)

表面上我们的就是Sql语句和我们的java对象进行映射,然后Mapper代理然后调用方法来操作数据库

底层的话我们就涉及到Sqlsession和Configuration

首先说一下SqlSession, 它可以被视为与数据库交互的一个会话,用于执行 SQL 语句(Executor执行器)获取映射器(Mapper)管理事务等操作

然后还有个全局配置Configuration,Configuration是Mybatis的核心配置类,里面有所有的配置信息,映射文件内容,甚至数据库连接池配置

SqlSession

也就是说我们的通过SqlSession来操作我们的数据库,SqlSession里面的执行器Executor来执行我们的具体的sql语句

我们的Executor其实有三种SimpleExecutor简单执行器,ReuseExecutor可重用执行器, BatchExecutor批量执行器

一个是每次使用都创建一个Statement对象,一个是可以以sql作为Key在Map<String,Statement>内查找我们的statement对象进行重用,一个是将所有的sql语句添加到批处理等待逐一执行

Configuration

很简单,就是一个mybatis的核心配置类,我们的主要的配置信息例如数据库连接池配置就在里面

再深入一点就讲一下我们的Mybatis的一二级缓存实现原理

一级缓存(在Sqlsession对象了里面):

我们有的话就用Executor执行器,从LocalCache里面查询,没有的话就从数据库中查然后放到我们的LocalCache里面

在分布式或者多个Sqlsession的情况下,可能会导致脏读问题

我们查询的时候会从Sqlsession的缓存里面查,那要是我们此时用SqlSession1和SqlSession2,我们要的数据在SqlSession2的缓存里面怎么办?我们一级缓存不能实现跨SqlSession,只能查不到然后查数据库

所以为了进一步优化多个SqlSession问题,我们就有了二级缓存

二级缓存(在Configuration里面):

在一级缓存查询之前,我们先通过CachingExecutor从二级缓存中进行查询

开启二级缓存之后呢,会被多个Sqlsession共享,所以它是一个全局的缓存

所以查询流程变成了:先查二级缓存,再查一级缓存,再查数据库

二级缓存对比一级缓存,它实现了Sqlsession之间的缓存数据的 共享


既然二级缓存可以优化查询?那为什么不默认用二级缓存?

数据一致性问题

  • 问题描述:二级缓存是跨SqlSession的,多个SqlSession共享同一个缓存。如果某个SqlSession更新了数据库,其他SqlSession可能仍然使用缓存中的旧数据,导致数据不一致。
  • 解决方案 :可以通过配置缓存的刷新策略(如flushInterval)或在更新操作后手动清除缓存来缓解。

2. 缓存失效问题

  • 问题描述 :当执行增删改操作时,MyBatis会清除相关缓存。但如果 其他系统或程序 直接修改了数据库,MyBatis无法感知,导致缓存中的数据与实际数据库不一致
  • 解决方案:需要结合其他机制(如数据库触发器或消息队列)来通知缓存失效。

3. 内存占用问题

  • 问题描述 :二级缓存默认存储在内存中,如果缓存的数据量过大,可能导致内存溢出(OOM)
  • 解决方案:可以通过配置缓存实现(如Ehcache、Redis)将缓存存储到磁盘或分布式缓存中。

4. 序列化问题

  • 问题描述二级缓存默认需要缓存对象实现 Serializable****接口以便序列化存储。如果对象未实现序列化接口,会导致缓存失败。
  • 解决方案 :确保所有缓存对象实现Serializable接口,或使用自定义的缓存实现。

5. 缓存粒度问题

  • 问题描述 :二级缓存的粒度是Mapper级别的,即一个Mapper的缓存会被所有查询共享。如果某个Mapper的查询结果差异较大,可能导致缓存命中率低,甚至缓存污染
  • 解决方案:可以通过自定义缓存键或使用更细粒度的缓存策略来优化。

6. 分布式环境下的问题

  • 问题描述 :在分布式环境中,默认的二级缓存是 本地缓存,不同节点之间的缓存无法共享,可能导致数据不一致。
  • 解决方案:使用分布式缓存(如Redis、Memcached)替换默认的本地缓存。

7. 缓存配置复杂

  • 问题描述 :二级缓存的配置相对复杂,需要根据业务场景调整缓存策略(如缓存清除策略、缓存刷新间隔等),配置不当可能导致性能下降或数据不一致。
  • 解决方案:仔细评估业务需求,合理配置缓存参数。

8. 不适合高并发写场景

  • 问题描述 :在高并发写场景下,频繁的增删改操作会导致 缓存频繁失效 反而降低性能
  • 解决方案:在高并发写场景下,建议禁用二级缓存,或使用更高效的缓存策
相关推荐
辛一一1 小时前
neo4j图数据库基本概念和向量使用
数据库·neo4j
{{uname}}1 小时前
利用WebSocket实现实时通知
网络·spring boot·websocket·网络协议
熊大如如2 小时前
Java 反射
java·开发语言
巨龙之路2 小时前
什么是时序数据库?
数据库·时序数据库
蔡蓝2 小时前
binlog日志以及MySQL的数据同步
数据库·mysql
猿来入此小猿2 小时前
基于SSM实现的健身房系统功能实现十六
java·毕业设计·ssm·毕业源码·免费学习·猿来入此·健身平台
goTsHgo3 小时前
Spring Boot 自动装配原理详解
java·spring boot
卑微的Coder3 小时前
JMeter同步定时器 模拟多用户并发访问场景
java·jmeter·压力测试
是店小二呀3 小时前
【金仓数据库征文】金融行业中的国产化数据库替代应用实践
数据库·金融·数据库平替用金仓·金仓数据库2025征文
pjx9873 小时前
微服务的“导航系统”:使用Spring Cloud Eureka实现服务注册与发现
java·spring cloud·微服务·eureka