一级缓存

  • Mybatis的一级缓存存放在SqlSession的生命周期,在同一个SqlSession中查询时,Mybatis会把执行的方法和参数通过算法生成缓存的键值,将键值和查询结果存入一个Map对象中。
  • 如果同一个SqlSession中执行的方法和参数完全一致,那么通过算法会生成相同的键值,当Map缓存对象中已经存在改键值时,则会返回缓存中的对象。(一个SqlSession连续两次查询 得到的是同一个java对象)
  • 任何的insert update delete操作都会清空一级缓存(增删改任何记录都会清空当前SqlSession的缓存)。

Spring整合Mybatis的时候一级缓存的问题:

  在未开启事物的情况之下,每次查询,spring都会关闭旧的sqlSession而创建新的sqlSession,因此此时的一级缓存是没有启作用的

  在开启事物的情况之下,spring使用threadLocal获取当前资源绑定同一个sqlSession,因此此时一级缓存是有效的

Spring结合Mybatis一级缓存失效的问题

二级缓存

每个sqlSession都有自己的一级缓存,多个sqlSession共享二级缓存

Mybatis二级缓存可以理解为存在SqlSessionFactory的生命周期

开启二级缓存(还有全局的开启方式,这里就不多说了):

1.在对应的XXXMapper.XML添加如下代码

  <cache></cache>

2. 在对应的select标签上添加(测试了下 不加也行)

useCache="true"

二级缓存特点:

SqlSession1调用getMapper获取对象user1

SqlSession1调用getMapper获取对象user2

user1和user2是同一个实例(原理同一级缓存)

如果二级配置可读写的缓存 <cache readOnly="false"/>(顾名思义 可以写的缓存吗 就是我写这个对象 不影响你,两个实例),不同SqlSession之间通过序列化和反序列化来保证通过缓存获取数据。

当另外一个SqlSess2开始执行SQL时候,不会去查数据库 会利用SqlSession1的缓存

SqlSession2调用getMapper获取对象user1_

SqlSession2调用getMapper获取对象user2_

user1_和user2_就是反序列化得到的结果 是不同的实例

此时虽然只发出一个SQL 但是:user1==user2  user1_<>user2_<>user1

当 readOnly="true"的时候

<cache readOnly="true"/>

user1==user2==user1==user2

二级缓存坑的地方:

你在OrderMapper.XML 和 UserMapp.XML的文件 都操作了User表的话,

当你使用OrderMapper.XML的SQL更新User表的时候,其他的SeqSession在OrderMapper.XML可以查到User表最新的数据,但是在UserMapp.XML查不到最新的数据

原因就是 二级缓存是基于某个XXXMapper.xml,每个Mapper直接独立,所以 不同Mapper操作同一张表的时候  使用二级缓存会造成脏读

这也就是没什么人开启二级缓存的主要原因

Redis缓存一致性

Mybatis默认提供的缓存是基于Map实现的内存缓存,已经可以基本满足应用。但当需要缓存大量数据的时候可以使用Redis缓存数据库来保存Mybatis的二级缓存数据。

但MySQL和Redis是两个事物,不好做强一致性。

简单点:可以延时双删+过期时间保证最终一致性。

双删的原因是防止并发情况下 update_db的过程中 其他事物发现redis缓存是空 重新赋予了Redis的值 此时如果赋值 是错误的数据

第二次延时删除的原因是要考虑MySQL数据库主从同步的耗时(如果立即删除 有别的线程从MySQL的从库查到的数据放到Redis中 此时的从库可能是没同步的错误数据)

rm_redis
update_db
sleep xxx ms
rm_redis

Mybatis一级缓存和二级缓存 Redis缓存的更多相关文章

  1. 第04项目:淘淘商城(SpringMVC+Spring+Mybatis)【第七天】(redis缓存)

    https://pan.baidu.com/s/1bptYGAb#list/path=%2F&parentPath=%2Fsharelink389619878-229862621083040 ...

  2. 使用本地缓存快还是使用redis缓存好?

    使用本地缓存快还是使用redis缓存好? Redis早已家喻户晓,其性能自不必多说. 但是总有些时候,我们想把性能再提升一点,想着redis是个远程服务,性能也许不够,于是想用本地缓存试试!想法是不错 ...

  3. Django缓存机制以及使用redis缓存数据库

    目录 Django 配置缓存机制 缓存系统工作原理 Django settings 中 默认cache 缓存配置 利用文件系统来缓存 使用Memcache来缓存: 使用Local-memory来缓存: ...

  4. Hibernate一级缓存和二级缓存深度比较

    1.什么是缓存 缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能.缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据, ...

  5. Redis缓存穿透和缓存雪崩以及解决方案

    Redis缓存穿透和缓存雪崩以及解决方案 Redis缓存穿透和缓存雪崩以及解决方案缓存穿透解决方案布隆过滤缓存空对象比较缓存雪崩解决方案保证缓存层服务高可用性依赖隔离组件为后端限流并降级数据预热缓存并 ...

  6. SpringBoot集成Redis分布式锁以及Redis缓存

    https://blog.csdn.net/qq_26525215/article/details/79182687 集成Redis 首先在pom.xml中加入需要的redis依赖和缓存依赖 < ...

  7. django 常用方法总结 < 手写分页-上传头像-redis缓存,排行 ...>

    1.不使用自带模块<Paginator>的手写分页功能views.pydef post_list(request): page = request.GET.get('page', 1) # ...

  8. Azure Redis 缓存的 ASP.NET 会话状态提供程序

    Azure Redis Cache 提供了一个会话状态提供程序,你可以使用其在缓存中(而不是内存中或在 SQL Server 数据库中)存储会话状态.要使用缓存会话状态提供程序,先首先配置缓存,然后使 ...

  9. 使用nginx+lua脚本读写redis缓存

    配置 新建spring boot项目增加redis配置 <dependency> <groupId>org.springframework.boot</groupId&g ...

随机推荐

  1. Javascript中中括号的几种形式

    有以下几种形式 var arr = []; var b = [1,1,1]; var c = b[0]; var obj = {'name':'tom','age':23}; var d = obj[ ...

  2. elasticsearch 深入 —— normalizer

    keyword字段的normalizer属性类似于分析器,只是它保证分析链生成单个token. 在索引关键字之前,以及在通过诸如match查询之类的查询解析器或者通过诸如term查询之类的术语级查询搜 ...

  3. vue开发 - 根据vue-router的meta动态设置html里title标签内容

    1.路由文件 :router/index.js 添加 meta属性配置: import Vue from 'vue' import Router from 'vue-router' import in ...

  4. Linux Shell 脚本学习第一天: 使用grep 命令,lsusb, ps -ef, 实现树莓派(Debian OS)时检测到依赖的USB设备启动后,启动终端自动执行shell脚本

    1.应用背景: 无人监测的设备,常需要设置应用程序开机启动,程序启动前需要保证调用的设备先启动,运行环境先启动. 2.test.sh部分源码 #!/bin/sh #查看桌面是否启动 while tru ...

  5. demo board boot mode

    demo扩展板 QSPI0_IO0_MIO2--A13--PS-MIO2 QSPI0_IO0_MIO3--A14--PS-MIO3 QSPI0_IO0_MIO4--B11--PS-MIO4 QSPI0 ...

  6. 苹果正制造一款疯狂的“16K”VR耳机,效果到底有多牛?

    苹果一直以来都有传闻称正在研发一副增强现实眼镜,但今天的一份报告显示,他们希望在虚拟现实领域与Google,微软和Facebook竞争. 据CNET报道,苹果公司着眼于2020年发布的将AR和VR技术 ...

  7. Pycharm的debug单步调试

    首先设置断点,点击行号显示的一侧,在指定行设置断点.比如这里,我们设断点在创建对象时: .如果这时我们直接右键run这个代码.他还是会直接运行,不会理会断点 结果 所以要右键选择run下面的debug ...

  8. Python的pip源切换为国内阿里云镜像

    Python的pip源切换为国内阿里云镜像 找到用户目录 C:\Users\用户\pip,如果不存在就新建该文件夹. 新建文件pip.ini,并用文本编辑器输入以下内容并保存 [global] ind ...

  9. C++ 概率算法 利用蒙特卡罗算法计算圆周率

    概率算法大致可分为4种形式: 数值概率算法: 蒙特卡罗算法: 拉斯维加斯算法: 舍伍德算法: 计算蒙特卡罗概率的算法实现: #include "stdio.h" #include ...

  10. C++ 穷举算法 鸡兔同笼

    #include "stdio.h" int qiongju(int head, int foot, int *chicken, int *rabbit) { int re, i, ...