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

【redis】事务详解,相关命令multi、exec、discard 与 watch 的原理

文章目录

  • 什么是事务
    • 原子性
    • 一致性
    • 持久性
    • 隔离性
  • 优势
    • 与 MySQL 对比
    • 用处
  • 事务相关命令
    • 开启事务——MULTI
    • 执行事务——EXEC
    • 放弃当前事务——DISCARD
    • 监控某个 key——WATCH
      • 作用场景
      • 使用方法
      • 实现原理
  • 事务总结

什么是事务

MySQL 事务:

  • 原子性:把多个操作,打包成一个整体
  • 一致性:事务执行之前和之后,数据都不能离谱(变化前后能对上号)
  • 持久性:事务中做出的修改都会存硬盘
  • 隔离性:事务并发执行,涉及到的一些问题

原子性

相比于 MySQL 来说,Redis 的事务就是个弟弟:

  • 原子性:Redis 的事务,到底有没有原子性?存在争议
    • 最原本的含义是把多个操作打包到一起,要么都执行,要么都不执行
    • Redis 做到了上述的含义,但是 MySQL 这里的原子性走的更远
      • MySQL 也是把多个操作打包到一起,要么全都执行成功,要么都不执行。如果事务中有操作执行失败的,就要进行回滚,把中间已经执行的操作,全部回退
      • Redis 事务中的如干操作,要是有失败的,无所谓。

Redis 把多个操作打包到一起执行,已经可以称为是原子性了,只是 MySQL 标杆,提高了“原子性”门槛,这就使人们谈到原子性的时候,更多的想到的是 MySQL 这样带回滚的原子性

所以,一般说到 Redis 的事务有没有原子性,更多的倾向于没有(或者弱化的原子性

一致性

Redis 没有约束,也没有回滚机制,事务执行过程中如果某个修改操作出现失败,就可能引起不一致的情况

  • 所以 Redis 事务不具备一致性

持久性

reids 本身就是内存数据库,数据是存储在内存中的,虽然 Redis 也有持久化机制(AOF),但这里的持久化机制和事务没有什么关系

  • MySQL 那边,事务百分百有持久性,Redis 这边把持久化机制关了。这是不一样的
  • 所以 Redis 事务不具备持久性

隔离性

Redis 是一个单线程模型的服务器程序,所有的请求/事务都是“串行”执行的。而谈到隔离性,都是并发执行才会涉及到的

  • 所以 Redis 事务不涉及隔离性

优势

Redis 事务,主要的意义就是为了“打包”,避免其他客户端的命令,插队插到中间

  • Redis 中实现事务,是引入了一个队列(每个客户端都有一个)
  • 开启事务的时候,此时客户端输入的命令,就会发给服务器,并且进入这个队列中(而不是立即执行)。当遇到了“执行事务”命令的时候,此时就会把队列中的这些任务都按顺序依次执行
    • 按顺序依次执行”是在 Redis 主线程中完成的,主线程会把事务中的操作都执行完,再处理别的客户端

与 MySQL 对比

Redis 的事务为什么就设计的这么简单,而不设计成和 MySQL 一样强大呢?

  • MySQL 的事务,在背后付出了很大的代价
    • 空间上,要花费更多的空间来存储更多的数据(实现回滚,就要额外开辟空间去存储必要的日志…)
    • 时间上,也要有更大的执行开销 (需要做更多额外的动作)

正是因为 MySQL 上述的问题,才有 Redis 上场的机会(简单高效的优势)

用处

什么时候需要用到 Redis 事务呢?

  • 如果我们需要把多个操作打包进行操作,使用事务是比较合适的

比如一个商品秒杀出售场景
一个货品 A,进行秒杀出售,市场火爆。此时最重要的就是不能出现“超卖”的情况(超卖:放货 5000 台,卖出了 5001 台)

一个典型的程序写法:

获取仓库中剩余的商品个数
if(个数 > 0) {下单成功;个数--;
}
  • 如果不加上任何限制,就可能会存在"线程安全"问题
  • 所以我们得让 下单成功个数-- 这两个操作是原子的
    • 以前在多线程中,是通过加锁的方式,来避免插队
    • Redis 中,就直接使用事务即可

使用事务之后的写法:

开启事务
get count
if count > 0decr count
执行事务
  • redis 接收到命令的时候,不会立即执行,只会将其按顺序放在队列中。当收到“执行事务”操作的时候,才会开始按顺序执行命令image.png
  • 第二个客户端的“执行事务”命令发过来之后,服务器才真正执行第二个事务中的内容。此时第一个事务执行命令已经运行过了,此时第二个事务 get 到的 count 就已经是第一个事务自减之后的结果了

这个场景中,没加锁,也能解决上述“超卖”问题

redis 命令里能进行条件判定吗?

  • redis 原生命令中确实没有这种条件判断定,但是 redis 支持 lua 脚本
    • lua 是另外一种编程语言,特点是小巧,很多程序都可以内嵌 lua 语言,从而去执行其他的语言
  • 通过 lua 脚本,就能实现上述的“条件判定”,并且也和事务一样是打包批量执行的
  • lua 脚本的实现方式,是 redis 事务的进阶版本

确实,redis 的事务的应用场景,没有 MySQL 的事务那么多(有点鸡肋的感觉)。redis 如果是按照集群模式部署,就不支持事务

事务相关命令

开启事务——MULTI

(猫体,不是马体)

开启一个事务,执行成功返回 OK
image.png

  • 此时只是在服务器的事务队列中,保存了上述请求,并没有真正执行命令
  • 此时如果另外开一个客户端,尝试查询这几个 key,是查询不到的

执行事务——EXEC

真正执行事务
image.png

  • 此时客户端才会真正把上述操作发给客户端,此时就可以获取到 key 的值了image.png

放弃当前事务——DISCARD

放弃当前事务,此时直接清空事务队列,之前的操作都不会真正执行到image.png|332
image.png|367

  • 前面输入的命令,都被丢弃了

当我们开启事务,并且给服务器发送若干命令之后,此时重启服务器,会怎么样?

  • 此时的效果就等同于 discard
  • 事务队列终归是内存中的结构,重启之后,自然是没有了

监控某个 key——WATCH

在执行事务的时候,如果某个事务中修改的值,被别的客户端修改了,此时就容易出现数据不一致的问题

作用场景

image.png|525
从时间上来看,客户端 1 是先发送了 set key 222,客户端 2 是后发送了 set key 333

  • 由于客户端 1 中,得是 exec 执行了,才会真正执行 set key 222。这个操作变成了实际上更晚执行的操作,最终 key 的值就是 222

使用方法

在刚才的场景中,就可以使用 watch 命令来监控这个 key,看看这个 key 在事务的 multiexec 之间,set key 之后,是否在外部被其他客户端修改了image.png|405

  • 被监控的 key 被修改之后,exec 之后返回值为 nil

实现原理

watch 的实现,类似与一个“乐观锁

  • 乐观锁/悲观锁不是指某个具体的锁,而是指的是某一类锁的特征
  • 乐观锁:加锁之前,就有一个心理预期,接下来锁的冲突概率较低
  • 悲观锁:加锁之前,也有一个心理预期,接下来锁的冲突概率较高
    • 冲突:两个线程针对同一个锁加锁,一个能加锁成功,另一个就得阻塞等待
  • 锁冲突概率高低,接下来要做的工作是不一样的

乐观锁在 https://yeeear.blog.csdn.net/article/details/141102212 这篇文章中有详细解释

rediswatch 就相当于是基于版本号这样的机制,来实现了“乐观锁”(就是 CAS 中的 ABA 问题的解决方法
image.png|608

  • watch 必须搭配事务使用,并且必须在 multi 之前使用
  • 如果 watch 的版本号和 exec 的版本号
    • 一致:说明当前 key 在事务开启到最终执行这个过程中,没有被别的客户端修改,于是才能真正进行设置
    • 不一致:说明 key 在其他客户端中改过了,因此此处就直接丢弃事务中的操作,exec 返回 nil

所以,watch 本质上就是给 exec 加了一个判定条件

事务总结

Redis 的事务,要比 MySQL 的事务,简单很多

  1. 原子性:Redis 的事务,并不支持回滚
  2. 一致性:Redis 并不会保证事务执行前后的内容统一
  3. 持久性:Redis 主要通过内存来存储数据
  4. 隔离性:Redis 自身作为一个单线程的服务器模型,上面处理的请求本质上都是串行执行的

四个关于事务的命令:

  1. 开启事务—— nulti
  2. 执行事务—— exec
  3. 放弃当前事务—— discard
  4. 监控某个 key 是否被修改—— watch

相关文章:

【redis】事务详解,相关命令multi、exec、discard 与 watch 的原理

文章目录 什么是事务原子性一致性持久性隔离性 优势与 MySQL 对比用处 事务相关命令开启事务——MULTI执行事务——EXEC放弃当前事务——DISCARD监控某个 key——WATCH作用场景使用方法实现原理 事务总结 什么是事务 MySQL 事务: 原子性:把多个操作&am…...

数据库基础知识点(系列七)

视图和索引相关的语句 1.引入视图的主要目的是什么? 答:数据库的基本表是按照数据库设计人员的观点设计的,并不一定符合用户的需求。SQL Server 2008可以根据用户需求重新定义表的数据结构,这种数据结构就是视图。视图是关系数据…...

FreeRTOS 队列结构体 xQUEUE 深度解析

一、核心成员与功能设计 FreeRTOS 的队列结构体 xQUEUE 是任务间通信(IPC)的核心数据结构,通过统一的设计支持队列、信号量、互斥量等多种同步机制。其设计体现了 ​**"数据拷贝 结构复用"** 的理念,兼顾轻量化与扩展…...

3.3 Taylor公式

1.定义 1.1 taylor公式 1.2 麦克劳林公式 1.3 推论 1.4 拉格朗日余项和皮亚诺型余项 2. 例题 3.几种特殊函数的麦克劳林展开...

2000-2019年各省地方财政行政事业性收费收入数据

2000-2019年各省地方财政行政事业性收费收入数据 1、时间:2000-2019年 2、来源:国家统计局、统计年鉴 3、指标:行政区划代码、地区、年份、地方财政行政事业性收费收入 4、范围:31省 5、指标说明:地方财政行政事业…...

Ftrans飞驰云联受邀参加“2025汽车零部件CIO年会“并荣获智象奖

2025年3月6日,由栖观汽车、栖观资讯和飞羽商务主办的“2025第二届中国汽车&零部件CIO年会暨智象奖颁奖盛典”于上海盛大召开,Ftrans飞驰云联作为国内领先的企业文件传输与数据交换解决方案提供商,受邀出席了年会,并凭借卓越的…...

C++vector常用接口和模拟实现

C中的vector是一个可变容量的数组容器,它可以像数组一样使用[]进行数据的访问,但是又不像C语言数组空间是静态的,它的空间是动态可变的。 在日常中我们只需要了解常用的接口即可,不常用的接口查文档即可。 1.构造函数 //空构造…...

oracle查询归档日志使用量

1.统计最近30天的数据 SELECT TRUNC(first_time, DD) "日期", SUM(blocks * block_size) / 1024 / 1024 / 1024 "大小(GB)" FROM v$archived_log WHERE first_time > SYSDATE - 30 -- 统计最近30天的数据 GROUP BY TRUNC(first_time, DD) ORDER BY 1 D…...

计算机二级WPS Office第七套WPS演示

解题过程...

2025-03-26 学习记录--C/C++-PTA 6-3 求链式表的表长

合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下。💪🏻 一、题目描述 ⭐️ 6-3 求链式表的表长 本题要求实现一个函数,求链式表的表长。 函数接口定义: &…...

【Mysql】事务管理:原理、操作与应用

文章目录 一、事务概述二、事务的特性(ACID)原子性(Atomicity)一致性(Consistency)隔离性(Isolation)持久性(Durability) 三、事务的操作事务的提交方式查看和…...

PHP框架 ThinkPHP 漏洞探测分析

目录 1. PHP历史利用最多的漏洞有哪些? 2. 如何在信息收集的过程中收到框架信息?有什么根据? 3. ThinkPHP框架漏洞扫描有哪些工具?红队攻击有哪些方式? 漏洞扫描工具 红队攻击方式 4. TPscan工具的主要作用及实际…...

A Brief History: from GPT-1 to GPT-3

This is my reading notes of 《Developing Apps with GPT-4 and ChatGPT》. In this section, we will introduce the evolution of the OpenAI GPT medels from GPT-1 to GPT-4. GPT-1 In mid-2018, OpenAI published a paper titled “Improving Language Understanding …...

大模型在支气管肺癌预测及临床决策中的应用研究报告

目录 一、引言 1.1 研究背景与意义 1.2 研究目的 二、大模型预测支气管肺癌的原理与技术基础 2.1 大模型简介 2.2 数据收集与预处理 2.3 模型训练与优化 三、术前预测 3.1 病情评估 3.1.1 肿瘤大小、位置及分期预测 3.1.2 转移风险预测 3.2 手术风险预测 3.2.1 患…...

SylixOS 中 select 原理及使用分析

1、select接口简介 1.1 select接口使用用例 select 是操作系统多路 I/O 复用技术实现的方式之一。 select 函数允许程序监视多个文件描述符,等待所监视的一个或者多个文件描述符变为“准备好”的状态。所谓的”准备好“状态是指:文件描述符不再是阻塞状…...

软考笔记——软件工程基础知识

第五章节——软件工程基础知识 软件工程基础知识 第五章节——软件工程基础知识一、软件工程概述1. 计算机软件2. 软件工程基本原理3. 软件生命周期4. 软件过程 二、软件过程模型1. 瀑布模型2. 增量模型3. 演化模型(原型模型、螺旋模型)4. 喷泉模型5. 基于构建的开发…...

FastGPT原理分析-数据集创建第二步:处理任务的执行

概述 文章《FastGPT原理分析-数据集创建第一步》已经分析了数据集创建的第一步:文件上传和预处理的实现逻辑。本文介绍文件上传后,数据处理任务的具体实现逻辑。 数据集创建总体实现步骤 从上文可知数据集创建总体上来说分为两大步骤: &a…...

基于Python的3D贴图制作技术研究与实践

摘要:本文深入探讨了利用Python进行3D贴图制作的技术,介绍了Python在3D图形领域的应用优势,阐述了3D贴图的基本原理和常见类型。详细讲解了借助Python的相关库,如Pillow、OpenCV、PyTorch3D开展3D贴图制作的流程,包括纹…...

【MySQL数据库】视图 + 三范式

视图 视图的基本介绍 MySQL中的视图(View)是一种虚拟的表,其内容是从一个或多个基本表中检索出来的。视图可以简化复杂的查询操作,提高查询效率,同时也可以对敏感数据进行安全性控制。下面是关于MySQL视图的一些基本…...

STM32学习笔记之存储器映射(原理篇)

📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨ 📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 📢:文章若有幸对你有帮助,可点赞 👍…...

如何通过数据可视化提升管理效率

通过数据可视化提升管理效率的核心方法包括清晰展示关键指标、及时发现和解决问题、支持决策优化。其中,清晰展示关键指标尤为重要。通过数据可视化工具直观地呈现关键绩效指标(KPI),管理者能快速、准确地理解业务现状&#xff0c…...

数据结构:利用递推式计算next表

next 表是 KMP 算法的核心内容,下面介绍一种计算 next 表的方法:利用递推式计算 如图 6.3.1 所示,在某一趟匹配中,当对比到最后一个字符的时候,发现匹配失败(s[i] ≠ t[j])。根据 BF 算法&…...

每日算法-250326

83. 删除排序链表中的重复元素 题目描述 思路 使用快慢指针遍历排序链表。slow 指针指向当前不重复序列的最后一个节点,fast 指针用于向前遍历探索。当 fast 找到一个与 slow 指向的节点值不同的新节点时,就将 slow 的 next 指向 fast,然后 …...

trino查询mysql报Unknown or incorrect time zone: ‘Asia/Shanghai‘

问题 trino查询mysql时报Error listing schemas for catalog mysql: java.sql.SQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.,trino的日志中看到Unknown or incorrect time zone…...

java学习笔记7——面向对象

关键字:static 类变量 静态变量的内存解析: 相关代码: public class ChineseTest {public static void main(String[] args) {System.out.println(Chinese.nation); //null 没赋值前System.out.println(Chinese.nation); //中国 静态变量赋值…...

leetcode day31 453+435

453 用最少数量引爆气球 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points ,其中points[i] [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。 一支弓箭可以沿着 x 轴从不同点 完全垂直 地…...

C++三大特性之继承

1.继承的概念及定义 回忆封装 C Stack类设计和C设计Stack对比。封装更好:访问限定符类的数据和方法放在一起 -> 避免底层接口的暴露,数据更加的安全,程序的耦合性更高迭代器的设计,封装了容器底层结构,在不暴露底层…...

PyQt QDoubleSpinBox控件用法详解

QDoubleSpinBox 是 PyQt中用于输入浮点数的控件,支持键盘输入和上下箭头调整数值。与QtSpinBox不同,QtSpinBox是用于输入整数的控件。 关键属性和方法 QDoubleSpinBox 的关键属性和方法如下表所示: 方法/属性说明setRange(min, max)设置数…...

解决Vmware 运行虚拟机Ubuntu22.04卡顿、终端打字延迟问题

亲测可用 打开虚拟机设置,关闭加速3D图形 (应该是显卡驱动的问题,不知道那个版本的驱动不会出现这个问题,所以干脆把加速关了)...

查询Marklogic数据库,因索引配置造成的返回数据count不同的问题

查询Marklogic数据库,因索引配置造成的返回数据count不同的问题 一,问题: 目前由两个MarkLogic DB,其中A表示所有的数据库统称,包含于BCD; 调用查询接口,通过A和B入口且相同的查询条件去查询B…...