springboot缓存篇之mybatis一级缓存和二级缓存
前言
相信很多人都用过mybatis
,这篇文章主要是介绍mybatis
的缓存,了解一下mybatis
缓存是如何实现,以及它在实际中的应用
一级缓存
什么是mybatis
一级缓存?我们先看一个例子:
@GetMapping("/list")
public Result<Void> listGoods(){GoodsExample goodsExample = new GoodsExample();goodsMapper.selectByExample(goodsExample);goodsMapper.selectByExample(goodsExample);return Result.okWithNullData();
}
上面这个例子有两个相同的查询方法,我们看看日志
我们看到即使两个查询方法一样,它也查询了两次数据库。mybatis
为了优化这种情况,既然两次查询语句一样,那么就将第一次结果缓存起来,那么第二次查询就不用再查数据库。
其实要实现这个功能也是挺简单的,你只需在方法上加上@Transactional
即可
@Transactional
public Result<Void> listGoods(){// 代码省略
}
再看看运行日志
我们可以看到只有一次查询,正常情况下每发起一次查询就会创建一个SqlSession
,查询结束了,SqlSession
就会被销毁。如果开启了事务,那么就可以为多个查询创建一个共同的SqlSession
,那么在同一个事务中,如果说存在相同的查询,那么后面的查询都会直接拿第一次查询的结果。
这么看来,mybatis
的一级缓存还不错,但现实告诉你如果你的项目比较大,比较复杂,比如分布式,如果使用mybatis
的一级缓存,很容易就踩坑了,因此一些大公司都会要求禁用它,而使用redis
mybatis
是默认开启一级缓存的,如果要关闭,可以在配置文件这样配置:
# 默认值是session,如果要关闭,设置成statement即可
mybatis.configuration.local-cache-scope=statement
为什么说很容易踩坑呢?
其实简单来说就是第一次缓存的结果,被另外的线程更新了,那么如果后面再拿到的数据就是脏数据。
总之禁用它,使用redis
代替它准没错
二级缓存
假如说现在有100个请求在同一时间请求列表数据,就上面那段代码而言,正常情况下要查询200次数据库
@GetMapping("/list")
public Result<Void> listGoods(){GoodsExample goodsExample = new GoodsExample();// 第一次查询goodsMapper.selectByExample(goodsExample);// 第二次查询goodsMapper.selectByExample(goodsExample);return Result.okWithNullData();
}
如果开启了一级缓存,那么也要查询100次,因此mybatis
就提供了二级缓存
二级缓存的设置也很简单,只需在Mapper.xml
文件中加上cache标签即可
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.dao.mapper.GoodsMapper"><!--缓存标签--><cache></cache><resultMap id="BaseResultMap" type="com.example.demo.domain.entity.Goods"><id column="id" jdbcType="BIGINT" property="id" /><result column="goods_name" jdbcType="VARCHAR" property="goodsName" /><result column="number" jdbcType="INTEGER" property="number" /><result column="create_time" jdbcType="TIMESTAMP" property="createTime" /><result column="update_time" jdbcType="TIMESTAMP" property="updateTime" /></resultMap><!--省略代码-->
当我们再次请求list接口时,看看控制台的日志
我们可以看到除了第一次查询要查询数据库外,后面的几次查询列表都是直接从缓存中拿数据
mybtais
二级缓存看上去好像挺好用的,但现实当中还是给你来个暴击,最好不要用。
我们要搞清楚它的作用范围,它时针对命名空间的,就比如说上面提到的mapper.xml
,如果说你部署在一个节点,那么就只有一个mapper.xml
,缓存的结果直接从这个空间下获取即可,但很多时候随着业务的增大可能要部署多个节点,那每个节点都有自己的mapper.xml
,而每个节点更新缓存只会更新自己节点的mapper.xml
,因此可能会出现下面的问题
客户端有个请求过来,从A节点获取列表数据的,如果有缓存查缓存,没有就查数据库,比如说meta 60产品数据,它的价格时6000元
客户端再发个请求过来,从B节点获取列表数据的,如果有缓存查缓存,没有就查数据库,比如说meta 60产品数据,它的价格时6000元
这是没有问题的,但现在管理人员调整了产品价格,从6000改成5000,他的这次更新请求刚好请求了B节点(客户端请求节点是随机的),此时B节点缓存刷新了
那现在是不是会出现这样的情况,有些用户看到的商品价格是6000(刚好访问了A节点,直接读取缓存),有些用户看到的价格却是5000(请求了B节点,B节点会重新查库)
所以mybtais
二级缓存慎用!
相关文章:

springboot缓存篇之mybatis一级缓存和二级缓存
前言 相信很多人都用过mybatis,这篇文章主要是介绍mybatis的缓存,了解一下mybatis缓存是如何实现,以及它在实际中的应用 一级缓存 什么是mybatis一级缓存?我们先看一个例子: GetMapping("/list") public…...

云计算认证有哪些?认证考了有什么用?
云计算作为一项快速发展的技术,对人才的需求持续增长。无论是男生还是女生,只要具备相关的技能和知识,都可以在云计算领域找到就业机会。 目前入行云计算最好最便捷的方式就是考证,拿到一个云计算相关的证书,就能开启…...

[ 云计算 | AWS 实践 ] Java 如何重命名 Amazon S3 中的文件和文件夹
本文收录于【#云计算入门与实践 - AWS】专栏中,收录 AWS 入门与实践相关博文。 本文同步于个人公众号:【云计算洞察】 更多关于云计算技术内容敬请关注:CSDN【#云计算入门与实践 - AWS】专栏。 本系列已更新博文: [ 云计算 | …...

c语言练习91:合并两个有序链表
合并两个有序链表 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 代码1: /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/typedef struct ListNode ListNode; struct Li…...

【Qt控件之QTabBar】介绍及使用
概述 QTabBar类提供了一个选项卡栏,例如用于选项卡对话框。 QTabBar非常简单易用,它使用预定义的形状绘制选项卡,并在选择选项卡时发出信号。它可以被子类化以调整外观和感觉。Qt还提供了一个实现好的QTabWidget。 每个选项卡具有一个tabT…...

最新Tuxera NTFS2023最新版Mac读写NTFS磁盘工具 更新详情介绍
Tuxera NTFS for Mac是一款Mac系统NTFS磁盘读写软件。在系统默认状态下,MacOSX只能实现对NTFS的读取功能,Tuxera NTFS可以帮助MacOS 系统的电脑顺利实现对NTFS分区的读/写功能。Tuxera NTFS 2023完美兼容最新版本的MacOS 11 Big Sur,在M1芯片…...
AndroidX使用Paho MQTT报找不到android/support/v4/content/LocalBroadcastManager
网上有直接引用support-v4包的,但我用的AndroidX,不能为这个类再引用support-v4 直接自己创建这个类,把androidx.localbroadcastmanager.content.LocalBroadcastManager改改就行。 虽然奇葩但能解决问题 package android.support.v4.content…...

Filter与Listener(过滤器与监听器)
1.Filter 1.过滤器概述 过滤器——Filter,它是JavaWeb三大组件之一。另外两个是Servlet和Listener 它可以对web应用中的所有资源进行拦截,并且在拦截之后进行一些特殊的操作 在程序中访问服务器资源时,当一个请求到来,服务器首…...

【刷题篇】反转链表
文章目录 一、206.反转链表二、92.反转链表 ||三、25. K 个一组翻转链表 一、206.反转链表 class Solution { public://使用头插//三个指针也可以ListNode* reverseList(ListNode* head) {if(headnullptr)return nullptr;ListNode* curhead;ListNode* newheadnew ListNode(0);L…...

【C语言小游戏--猜数字】
文章目录 前言1.游戏描述2.代码实现2.1打印菜单2.2构建基础框架2.3玩游戏2.3.1生成随机数2.3.1.1rand()2.3.1.2srand()2.3.1.3time() 2.3.2game() 2.4自己设定猜的次数 3.完整代码 前言 猜数字小游戏是我们大多数人学习C语言时都会了解到的一个有趣的C语言小游戏,下…...
Vue计算属性computed和监听watch
1.计算属性 初衷:为了解决模块里面有太多的计算逻辑让模版难以维护。 计算属性可以依赖一个数据也可以依赖多个数据的变化 使用场景: 商品单价和数量改变时,商品总价更改。如果写在方法里面,那么每次修改商品单价和数量时都会…...

HTTP介绍 原理 消息结构 客户端请求 服务器响应 HTTP状态码
一、HTTP介绍二、HTTP工作原理HTTP三点注意事项 三、HTTP消息结构四、客户端请求消息五、服务器响应消息HTTP请求方法 七、HTTP响应头信息八、HTTP状态码(HTTP Status Code)下面是常见的HTTP状态码:HTTP状态码分类HTTP状态码列表 一、HTTP介绍…...

linux性能分析(五)如何学习linux性能优化
一 如何学习linux性能优化 强调: 由于知识记忆曲线以及某些知识点不常用,所以一定要注重复习思考: 如何进行能力转义以及能力嫁接? --> 真正站在巨人的肩膀上性能调优的目的: 不影响系统稳定性的资源最大利用化补充: 性能…...
1402. 做菜顺序 --力扣 --JAVA
题目 一个厨师收集了他 n 道菜的满意程度 satisfaction ,这个厨师做出每道菜的时间都是 1 单位时间。 一道菜的 「 like-time 系数 」定义为烹饪这道菜结束的时间(包含之前每道菜所花费的时间)乘以这道菜的满意程度,也就是 time[i…...
Springboot踩坑-request body重复读问题
背景 在一次业务开发中,由于需要在拦截器中对一个http请求中request body内容做解析和判断,所以用了httpServletRequest的getInputStream解析了request body内容,之后导致了拦截器处理成功后,原来的业务接口处报request body not…...

C++ 类和对象(六)赋值运算符重载
1 运算符重载 C为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数, 也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。 函数名字为:关键字operator后面接需…...
rust学习-trait std::cmp::PartialEq、Eq、PartialOrd、Ord
PartialEq 介绍 pub trait PartialEq<Rhs = Self> whereRhs: ?Sized, {// Required method,后文有讲解这个注释fn eq(&self, other: &Rhs) -> bool;// Provided method,后文有讲解这个注释fn ne(&self, other: &Rhs) -> bool {... } }x.eq(y)…...
k8s pod根据指标自动扩缩容举例
目录 基于 内存 指标实现pod自动扩缩容 举例配置 基于 cpu 指标实现pod自动扩缩容 举例配置 基于请求数(次/秒) 指标实现pod自动扩缩容 举例配置 基于 http请求响应时间 (ms) 指标实现pod自动扩缩容 举例配置 基于 Java GC暂停时间 (ms) 指标实现…...
深、浅拷贝之间的关系
深、浅拷贝之间的关系 什么是赋值 赋值是将某一数值或对象赋给某个变量的过程,分为下面 2 部分 基本数据类型:赋值,赋值之后两个变量互不影响引用数据类型:赋址,两个变量具有相同的引用,指向同一个对象&…...

服务器数据恢复-某银行服务器硬盘数据恢复案例
服务器故障&分析: 某银行的某一业务模块崩溃,无法正常使用。排查服务器故障,发现运行该业务模块的服务器中多块硬盘离线,导致上层应用崩溃。 故障服务器内多块硬盘掉线,硬盘掉线数量超过服务器raid阵列冗余级别所允…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...

OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...