【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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/74367.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java SE】单例设计模式

参考笔记:深入理解Java设计模式:单例模式及其饿汉式与懒汉式的对比,-CSDN博客 目录 1.什么是设计模式 2.经典设计模式 3.单例设计模式(static属性/方法经典使用场景 ) 3.1 饿汉式单例模式 3.2 懒汉式单例模式 4.补充 1.什么…

【day2】数据结构刷题 栈

一 有效的括号 给定一个只包括 (,),{,},[,] 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应的…

蓝桥杯 劲舞团

问题描述 小蓝最近迷上了一款名为 “劲舞团” 的游戏。 在游戏中,只要按照给出的键位提示依次按出对应的键位,游戏人物便可以跟随节奏跳舞。 对于连续的 K 次正确敲击,如果任意连续两次敲击之间的时间间隔都小于等于 1 秒(即 1…

数据库数值函数详解

各类资料学习下载合集 ​​https://pan.quark.cn/s/8c91ccb5a474​​ 数值函数是数据库中用于处理数值数据的函数,可以用于执行各种数学运算、统计计算等。数值函数在数据分析及处理时非常重要,能够帮助我们进行数据的聚合、计算和转换。在本篇博客中,我们将详细介绍常用的…

关于金融开发领域的一些专业知识总结

目录 1. 交易生命周期 1.1 证券交易所 1.1.1 交易前 1) 订单生成(Order Generation) 2) 订单管理(Order Management) 1.1.2 交易执行 3) 交易匹配(Trade Matching) 1.1.3 交易后 4) 交易确认&…

Leetcode 3495. Minimum Operations to Make Array Elements Zero

Leetcode 3495. Minimum Operations to Make Array Elements Zero 1. 解题思路2. 代码实现 题目链接:3495. Minimum Operations to Make Array Elements Zero 1. 解题思路 这一题的话核心就是统计对任意自然数 n n n,从 1 1 1到 n n n当中所有的数字对…

Vue 3 + TypeScript 实现视频播放与字幕功能:集成西瓜播放器 XGPlayer

文章目录 1. 前言:视频播放器的重要性2. 准备工作2.1 安装 Vue 3 项目2.2 安装 XGPlayer 和相关依赖 3. 实现视频播放3.1 初始化 XGPlayer 4. 添加字幕功能4.1 配置字幕 4.2 字幕文件格式5. 增加交互性完整的代码,仅供参考6. 总结 在现代 Web 开发中&…

MacOS安装 nextcloud 的 Virtual File System

需求 在Mac上安装next cloud实现类似 OneDrive 那样,文件直接保存在服务器,需要再下载到本地。 方法 在 官网下载Download for desktop,注意要下对版本,千万别下 Mac OS默认的那个。 安装了登录在配置过程中千万不要设置任何同…

.NET 9 彻底改变了 API 文档:从 Swashbuckle(Swagger) 到 Scalar

示例代码下载:https://download.csdn.net/download/hefeng_aspnet/90404652 摘要 API 文档是现代软件开发的支柱。随着 .NET 9 从 Swashbuckle 转向 Microsoft.AspNetCore.OpenApi,开发人员需要新的策略来保持高效。本文探讨了这些变化,并介…

深入剖析Java虚拟机(JVM):从零开始掌握Java核心引擎

📌 引言:为什么每个Java开发者都要懂JVM? 想象你是一名赛车手,Java是你的赛车,而JVM就是赛车的引擎。 虽然你可以不关心引擎内部构造就能开车,但要想在比赛中获胜,必须了解引擎如何工作&#…

怎么连接linux服务器的桌面

一、使用 VNC(Virtual Network Computing) 1. 服务器端配置(Ubuntu 22.04 示例) # 安装 VNC 服务器(以 TigerVNC 为例) sudo apt update sudo apt install tigervnc-standalone-server tigervnc-xorg-ext…

elasticsearch 通用笔记

文章目录 一、前言二、内容说明1、目录简介2、本文例子前提内容 三、操作内容1、设置ES为服务2、查看健康度参数解析 3、索引相关查询3.1、查询指定索引内容3.1.1、匹配查询3.1.2、精确匹配(不尝试分词)3.1.3、范围查询3.1.4、id查询3.1.5、通配符及前缀…

windows安装配置FFmpeg教程

1.先访问官网:https://www.gyan.dev/ffmpeg/builds/ 2.选择安装包Windows builds from gyan.dev 3. 下滑找到release bulids部分,选择ffmpeg-7.0.2-essentials_build.zip 4. 然后解压将bin目录添加path系统变量:\ffmpeg-7.0.2-essentials_bui…

强大的AI网站推荐(第二集)—— V0.dev

网站:V0.dev 号称:前端开发神器,专为开发人员和设计师设计,能够使用 AI 生成 React 代码 博主评价:生成的UI效果太强大了,适合需要快速创建UI原型的设计师和开发者 推荐指数:🌟&…

c#知识点补充4

1.发布者订阅模式 发布者 订阅者 俩者直接的关联使用

01、聊天与语言模型

一、简单说明模型 LLM目前有两种API提供 LanguageModel:接收一个a作为输入并返回一个b作为输出,这种是已经过时的ChatLanguageModel:接收多个输入,然后返回相应的输出 ChatLanguaggeModel是LangChain4j中LLM交互低级API&#x…

SQL的DCL,DDL,DML和DQL分别是什么

SQL(Structured Query Language)包括以下四种主要语言类别,分别用于不同的数据库操作: 1. DCL(Data Control Language,数据控制语言) 用于控制数据库访问权限和安全。 常见命令: …

spring boot maven一栏引入本地包

1、在项目跟目录下建立文件夹&#xff0c;比如libs 2、maven依赖 <dependency><groupId>com.hikvision.ga</groupId><artifactId>artemis-http-client</artifactId><version>1.1.10</version><scope>system</scope>&l…

连续型随机变量及其分布

连续型随机变量 数学公式可以看作一门精确描述事物的语言&#xff0c;比语言尤其是汉语的模糊性精确多了&#xff01;离散型数据的处理可以通过枚举和相加进行处理。而连续型数据则没有办法这样处理。我们必须要通过函数和取值区间还有微积分计算。 &#xff3b;定义1&#x…

AI重构SEO关键词优化路径

内容概要 人工智能技术的深度应用正在推动SEO优化进入全新阶段。传统关键词优化依赖人工经验与静态规则&#xff0c;存在效率瓶颈与策略滞后性缺陷。AI技术通过智能语义分析系统&#xff0c;能够穿透表层词汇限制&#xff0c;精准捕捉用户搜索意图的语义关联网络&#xff0c;结…