[Redis#16] 事务 | vs Mysql | 命令 | WATCH的实现

目录

什么是事务

实现事务的方式

Redis 事务与 MySQL 事务的对比

应用场景:防止超卖

Lua 脚本增强

事务操作

MULTI & EXEC

DISCARD

WATCH

WATCH 的实现原理


什么是事务

[MySQL#12] 事务(1) | ACID | commit | 回滚 | 常见操作

Redis 的事务和 MySQL 的事务概念上是类似的,都是把一系列操作绑定成一组,让这一组能够批量执行。然而,需要注意的是 Redis 事务与 MySQL 事务存在以下几点区别:

  • 弱化的原子性: Redis 没有 "回滚机制"。它只能保证这些操作 "批量执行",但不能做到 "一个失败就恢复到初始状态"。
  • 不保证一致性: Redis 不涉及 "约束",也没有回滚机制。MySQL 的一致性体现在运行事务前后结果的合理性,不会出现中间非法状态。
  • 不需要隔离性: Redis 事务没有隔离级别,因为 Redis 是单线程处理请求,不会并发执行事务。
  • 不需要持久性: Redis 数据保存在内存中,是否开启持久化由 redis-server 自行决定,这与事务无关。

Redis 事务本质上是在服务器上创建了一个 "事务队列"。

每次客户端在事务中进行一个操作,都会先将命令发送给服务器并放入 "事务队列"(但并不会立即执行),而是在收到 EXEC 命令后,才真正执行队列中的所有操作。

  • 这么多特性Redis都不具备,那么Redis的事务到底有什么意义呢?
    Redis的事务最主要的意义就是为了"打包",避免其他客户端的命令插队到中间.

最开始官网还说原子性,后来就把这句话给删了,官方也是有点虚的


实现事务的方式

  • Redis 在实现事务时引入了队列机制。每个客户端都有一个独立的队列。
  • 当开启事务时,客户端输入的命令会发送给服务器并进入这个队列中,而不是立即执行。
  • 只有当遇到 "执行事务" 的命令(如 EXEC)时,才会把队列中的任务按照录入顺序依次执行。
  • 这些事务操作是在 Redis 主线程中完成的。
  • 主线程会确保将事务中的所有操作执行完毕后,再处理其他客户端的请求。

Redis 事务与 MySQL 事务的对比

虽然 Redis 事务的功能没有 MySQL 强大,但 MySQL 为了实现强大的事务功能也付出了不小的代价:

  • 空间上:MySQL 需要花费更多空间来存储额外的数据,例如用于回滚段和多版本控制。
  • 时间上:MySQL 的事务处理需要更大的执行开销,包括锁管理、日志记录等。

正因为 MySQL 事务存在上述问题,Redis 提供了一种轻量级的解决方案,适用于某些特定场景。

应用场景:防止超卖

在购物网站秒杀场景中,可能会出现超卖的情况,即商家放了5000个商品,但由于并发问题导致下单成功了5001个。为避免这种情况,在多线程环境中我们曾通过加锁的方式来解决。

如果引入 Redis,则可以直接使用其事务机制解决问题。

例如,考虑两个客户端几乎同时下单的情况:

  • 客户端1开启一个事务,该事务被放入 Redis 的事务队列中;
  • 客户端2同样开启一个事务,并被放入队列;
  • 当事务1收到执行命令被执行时,它会减少库存计数(count--);
  • 当轮到事务2执行时,由于此时 count>0 的条件不再满足,所以事务2将不会改变数据库状态,从而避免了超卖问题。

Lua 脚本增强

值得注意的是,尽管 Redis 本身不支持像编程语言那样的条件判断(如 if),但它可以引入 Lua 脚本来实现复杂的逻辑判断。通过 Lua 脚本,我们可以实现上述条件的判断逻辑,进一步强化 Redis 事务的应用能力。


事务操作

MULTI & EXEC
  • multi:开启事务
  • exec:提交事务

示例:

开启事务后,不论输入什么指令,都返回QUEUE,此时会在客户端维护一个队列,将所有指令入队列。最后执行exec提交事务,所有的指令再同时返回。

DISCARD
  • discard:取消事务

示例:

开启事务后,输入两个值,再通过discard取消事务,最后查询key1发现插入失败,因为这个请求没有提交给客户端,而是直接被取消了。

另外的,如果在事务执行的过程中,Redis崩溃,恢复后效果和discard一样,就是事务内的操作都取消了。

WATCH

现有以下场景:

  • 从时间上来看,客户端1 是先发送了 set key 222,客户端2 是后发送了 set key 333
  • 由于 客户端1 中,得是 exec 执行了,才会真正执行 set key 222 这个操作
  • set key 222 变成了实际上更晚执行的操作!! 最终值就是 222

在事务执行过程中,客户端1无法感知外部的变化,客户端2的命令被 客户端 1 事务覆盖了

  • watch:让事务可以监听外部的变化,如果监听的数据被外部改变,操作失效

语法:

左侧的终端,在执行事务前开启了watch key,开启事务后set key 222。在事务提交前,右侧终端修改了key 333,随后左侧终端提交事务时,返回了nil表示事务操作无效。

因为watch监听到了key被外部修改,此时自己的事务提交可能会影响其它客户端,于是取消该操作。

如果想要取消watch,可以使用unwatch指令:

unwatch

这个指令没有参数,一次性取消所有key的监听。

WATCH 的实现原理

WATCH 的实现原理类似于我们在并发编程中学习的乐观锁机制,即解决 CAS(Compare-And-Swap)中的 ABA 问题的策略。乐观锁假设冲突很少发生,并在检测到冲突时采取相应的措施。与 ABA 问题中的实现策略相似,Redis 的 WATCH 基于版本号机制实现了乐观锁。

watch使用了一种版本号的机制每个数据都有一个版本号,每次修改key的值时,都会修改其版本号。

  • 在watch key时,会记录当前的版本号。
  • 在事务提交时,检测当前的版本号是否与之前的版本号相同,如果相同那么提交成功,如果版本号不同,说明有别的用户修改了数据,导致版本号修改,当前事务将不会执行并返回失败。

WATCH 本质上是给 EXEC 加上了一个对特定 key 的判定条件只有当所有被 WATCH 的 key 自从 WATCH 开始以来没有被修改过的情况下,事务才会被执行;否则,事务将被取消。

举例说明

可以将 WATCH 比喻为判断老公是否出轨的情景:

  • 离开家之前:把枕头放到一个特定的位置,并拍下一张照片作为记录。
  • 回家之后:检查枕头的位置是否发生了改变。如果位置变了,则可以推测出在这段时间内有人移动了枕头(在这个比喻中意味着老公可能出轨了)。

同样的逻辑应用于 Redis 中:

  • WATCH key3:开始监视 key,此时记录下 key 的状态(版本号)。
  • 尝试执行事务:如果在此期间 key 被其他客户端修改过,那么提交事务时就会发现 key 的状态已经改变,从而导致当前事务执行失败。如下就返回了 Nil

乐观锁与悲观锁

  • 乐观锁:乐观锁假设在加锁之前,锁冲突的概率较低。因此,在加锁之前不会进行任何检查,而是直接进行操作。如果在操作完成后发现冲突,则会进行重试。
  • 悲观锁:悲观锁假设在加锁之前,锁冲突的概率较高。因此,在加锁之前会进行检查,确保没有其他线程正在操作该资源。如果发现冲突,则会阻塞等待。

实现示例

  • 在 C++ 和 Linux 中涉及的锁,如 mutex 和 std::mutex,都是悲观锁。
  • Java 中的 synchronized 关键字则可以在悲观/乐观之间自适应。

事务命令 sum:

  • MULTI:开启一个事务,执行成功返回 OK。
  • EXEC:真正执行事务。每个操作加入事务时会提示 "QUEUED",表示命令已经进入客户端的队列,直到 EXEC 执行时才会真正发送给服务器。
  • DISCARD:放弃当前事务,清空事务队列,之前的操作都不会真正执行。
  • WATCH:用于监控一组具体的 key,在提交事务时如果发现 key 被其他客户端修改过,则事务执行失败。
  • UNWATCH:取消对 key 的监控,相当于 WATCH 的逆操作。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

day03-分析产品原型-课程

1. 开发流程 2. 分析产品原型 2.1 业务流程 产品原型图: 两个业务模块之间使用异步通信 2.2 查询课程列表-接口 https://apifox.com/apidoc/shared-3076deb7-ecde-4519-8e57-390d336aef4c 2.2.1 课表VO 前端课表的相关参数: 现在还不能一步到位&a…

电子商务人工智能指南 2/6 - 需求预测和库存管理

介绍 81% 的零售业高管表示, AI 至少在其组织中发挥了中等至完全的作用。然而,78% 的受访零售业高管表示,很难跟上不断发展的 AI 格局。 近年来,电子商务团队加快了适应新客户偏好和创造卓越数字购物体验的需求。采用 AI 不再是一…

CANoe IG实现信号遍历

CANoe IG也可以实现信号遍历的功能,设置如下: 注意事项: 选择 Range of values,是实现信号设定值范围内(6)的遍历 Hold time 要设置成和周期一致,如果不一致,则信号变化和周期不一…

AI大模型驱动数据分析:利用自然语言实现数据查询与可视化(1)

在当今AI驱动的时代,数据分析已成为各行各业不可或缺的能力。然而,传统的数据分析流程通常需要掌握SQL、数据处理和可视化等多项专业技能,这对非技术背景的业务人员来说是一个不小的挑战。 想象一下,当数据中心的负责人打开手机时…

蓝桥杯训练15——穿越雷区

from collections import deque def bfs(leiqu): n len(leiqu) # 定义四个方向:右、下、左、上 directions[(0,1),(0,-1),(1,0),(-1,0)] # 初始化访问标记矩阵 visited [[False] * n for _ in range(n)] queue deque() #…

【STL】用一张哈希表封装unordered_set和unordered_map

哈希表源代码 这里是使用开散列实现的哈希表&#xff0c;为了和库里的哈希表进行区分&#xff0c;我将哈希表放入到了命名空间中 //确保取余运算符两边是正整数&#xff0c;下标不能是负整数 template<class K> struct DefaultHashFunc {size_t operator()(const K&…

搜索二维矩阵 II

搜索二维矩阵 II 编写一个高效的算法来搜索 *m* x *n* 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9…

嵌入式入门Day24

数据结构Day5 树形结构相关概念二叉树相关概念二叉树的状态二叉树性质二叉树的存储二叉树根据已有序列推出树的结构练习 算法相关概念算法特性算法的设计要求时间复杂度排序算法冒泡排序&#xff08;改良版&#xff09;选择排序&#xff08;O(n^2)&#xff09;直接插入排序&…

百度网盘qzxing-master.zip

qzxing 这是一个针对 ZXing 条形码图像处理库的 Qt/QML 封装库。 支持以下类型的条形码解码&#xff1a; UPC-AUPC-EEAN-8EAN-13ITFCode 39Code 93Code 128&#xff08;GS1&#xff09;Codabar二维码数据矩阵Aztec&#xff08;测试版&#xff09;PDF 417 支持以下类型的条形…

Ping32与天锐绿盾加密软件对比:哪款防泄密软件适合您的企业?

企业数据泄漏事故层出不穷&#xff0c;为了有效防止机密信息的泄露&#xff0c;选择一款合适的防泄密软件显得尤为重要。Ping32和天锐绿盾加密软件都是市场上比较受欢迎的防泄密工具&#xff0c;那么它们各自的优势和差异是什么呢&#xff1f;让我们一起来了解。 1. 安全性&…

PDF拆分之怎么对批量的PDF文件进行分割-免费PDF编辑工具分享

>>更多PDF文件处理应用技巧请前往 96缔盟PDF处理器 主页 查阅&#xff01; ——————————————————————————————————————— 当然了&#xff0c;单个文件或者其他任意的文件个数的拆分也是支持的&#xff01; 序言 我之前的文章也有…

简易url解码器(定义python单行函数工具)

被%编码的url如同天书&#xff0c;自拟一个单行函数解析还原&#xff0c;方便相认。 (笔记模板由python脚本于2024年12月05日 15:14:17创建&#xff0c;本篇笔记适合学习Url的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&…

JavaWeb项目打包、部署至Tomcat并启动的全程指南(图文详解)

前言 我们想要部署一个javaWeb项目到tomcat上&#xff0c;需要了解一些概念 什么是tomcat&#xff1f; Tomcat 是 Apache 软件基金会&#xff08;Apache Software Foundation&#xff09;下的一个开源项目&#xff0c;主要用于实现 Java Servlet、JavaServer Pages&#xff08;…

【笔记2-5】ESP32:freertos消息队列

主要参考b站宸芯IOT老师的视频&#xff0c;记录自己的笔记&#xff0c;老师讲的主要是linux环境&#xff0c;但配置过程实在太多问题&#xff0c;就直接用windows环境了&#xff0c;老师也有讲一些windows的操作&#xff0c;只要代码会写&#xff0c;操作都还好&#xff0c;开发…

亚马逊云科技大语言模型加速OCR应用场景发展

目录 前言Amazon Bedrock关于OCR解决方案Amazon Bedrock进行OCR关键信息提取方案注册亚马逊账号API调用环境搭建 总结 前言 大语言模型是一种基于神经网络的自然语言处理技术&#xff0c;它能够学习和预测自然语言文本中的规律和模式&#xff0c;可以理解和生成自然语言的人工…

贪心算法 part03

文章参考来源代码随想录 134. 加油站 方法一分类讨论&#xff1a; 情况一&#xff1a;如果gas的总和小于cost总和&#xff0c;那么无论从哪里出发&#xff0c;一定是跑不了一圈的 情况二&#xff1a;rest[i] gas[i]-cost[i]为一天剩下的油&#xff0c;i从0开始计算累加到最…

【JAVA练习】力扣860.柠檬水找零

题目&#xff1a; 解题思路&#xff1a; 可能面临3种面额&#xff0c; 5美元&#xff0c;不找还&#xff0c;5美元钞票数量加110美元&#xff0c;找还5美元&#xff0c;5美元钞票数量减1&#xff0c;10美元钞票加120美元&#xff0c;找还15美元&#xff0c;分为一张10美元 一…

Telnet不安全?如何配置使用更安全的STelnet远程登录华为AR1000V路由器?

在上一篇文章中&#xff0c;我们介绍了如何配置一台全新的AR1000V&#xff0c;来实现通过Telnet远程登录设备&#xff08;如何配置使用Telnet远程登录华为AR1000V路由器&#xff1f;&#xff09;。其实&#xff0c;在之前的文章中&#xff0c;我们已经介绍过Telnet是一种不安全…

UE----Ios打包笔记

UE 打包 IOS 软件 1.前期准备 1.1. 首先我们需要 一台装有Xcode 的MAC笔记本&#xff08;知道开机密码 最好是空的笔记本 剩余内存要大 &#xff09; 1.2. 一台IOS手机 1.3. 一个申请了开发者账户的 Apple ID (苹果账号) 知晓账号与密码最好 因为很麻烦 1.4. UE 需要 的 兼…

计算机毕业设计Python轨道交通客流预测分析可视化 智慧交通 机器学习 深度学习 人工智能 爬虫 交通大数据

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…