Redis(十三) 事务

news2024/11/16 8:39:09

在这里插入图片描述

文章目录

  • 前言
  • 事务的特性
  • Redis事务的执行原理
  • Redis中使用事务
    • WATCH UNWATCH实现乐观锁

前言

前面我们学习 MySQL 的时候,肯定也学习了事务。事务是什么?给大家举个例子:假如我给朋友微信转账,我给他转了 100 块钱,当我输入完成密码了之后,我的微信余额减了 100,但是这时我的微信突然没信号了,换句话就是微信服务器突然挂了,当微信服务器重新启动之后,我问我那个朋友 100 块钱收到了没,他说没有,我就去看我的微信余额,发现 100 块钱扣掉了,那么这时候就出现问题了,我的微信余额减少了,但是朋友的微信余额没有增加。遇到这种问题该如何解决呢?那就是使用事务,事务中的语句要么全部执行,要么全部不执行。Redis 中也有事务这个概念,但是和 MySQL 的事务是有区别的。

事务的特性

前面学习的 MySQL 事务有四种特性(ACID):

  1. 原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行。
  2. 一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致。
  3. 隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。
  4. 持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。

上面是 MySQL 事务的特性,Redis 事务对比于 MySQL 事务而言,那真的就是一句话:没有可比性。

原子性是事务中的操作要么全部执行,要么一个都不执行。当事务中的某个操作出现错误的时候,就会将之前的操作进行回滚,回滚到事务开启前的状态,只有操作全部正确执行的时候,才不会发生回滚。但是对于我们的 Redis 来说,如果事务中的操作出现了错误之后,redis 只会报错,然后继续执行事务后面的操作,而不会发生回滚。那么 Redis 的这种操作可以称作是原子性吗?其实也是有的,但是这种性质叫做弱原子性,也可以说 Redis 不具有原子性,大家对于原子性的定义是有歧义的,所以对于 Redis 是否具有原子性也是存在歧义的。

一致性是指在事务开始之前和事务结束以后,数据库的完整性没有被破坏。因为 Redis 的事务不具有回滚的功能,所以也就无法保证事务的一致性,也就是说 Redis 不具有一致性。

持久性是指事务的操作对于数据库的改变是永久的,而由于我们的 Redis 操作数据都是在内存中的,内存中的数据是易失的,不具有持久性,所以 Redis 不具有持久性。

隔离性是指多个事务之间的操作是互不影响的,而我们的 Redis 是单线程模型的服务器程序,所以也就不存在多个事务同时执行的情况,就不存在所谓的隔离性特性。

啊?既然 Redis 的事务 ACID 特性都没有,那么 Redis 的事务是干嘛的啊?其实 Redis 事务的主要功能就是为了“打包”,将一个客户端发送的事务之内的操作放在一起,按照顺序执行,防止被其他客户端发送来的请求命令插队、干扰。

Redis事务的执行原理

Redis 实现事务引入了队列,当客户端开启事务的时候,接下来输入的命令 redis 服务器不会立即执行这些命令,而是会将这些命令放入这个队列中(这个队列是每个客户端都对应的有一个)。只有当遇到执行事务这个命令的时候,队列中的命令才会依次执行,而这个队列中的命令只有全部执行完才会执行其他客户端对应的队列中的命令。

那么为什么 Redis 的事务搞得这么简单,而不是像 MySQL 那样功能齐全呢?MySQL 的事务功能齐全那是需要付出代价的,需要付出更多的空间和时间,而 Redis 又以快著称,因为 redis 操作的对象是内存,内存的价格比硬盘高不少,所以完善 redis 的事务功能就以为需要牺牲速度和空间,那这样还不如直接使用 MySQL。

Redis中使用事务

在 redis 中实现事务需要依赖 MULTIEXECDISCARD命令。

  • MULTI:开启事务
  • EXEC:执行事务
  • DISCARD:丢弃事务

现在一个客户端中开启事务,并且向队列中添加一些命令,但是不执行事务。再开启一个窗口,查看事务中的操作是否执行:

127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set key1 111
QUEUED
127.0.0.1:6379> set key2 222
QUEUED
127.0.0.1:6379> set key3 333
QUEUED
127.0.0.1:6379>
127.0.0.1:6379> get key1
(nil)
127.0.0.1:6379> get key2
(nil)
127.0.0.1:6379> get key3
(nil)

然后执行事务,再看是否执行操作:

127.0.0.1:6379> EXEC
1) OK
2) OK
3) OK

使用 EXEC 执行事务之后,返回的是事务中的每个操作的返回值

127.0.0.1:6379> get key1
"111"
127.0.0.1:6379> get key2
"222"
127.0.0.1:6379> get key3
"333"

上面就是一个完整的事务,那么如果事务中的操作出现了错误,会发生什么:

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set key4 444
QUEUED
127.0.0.1:6379> setget key5 555
(error) ERR unknown command `setget`, with args beginning with: `key5`, `555`, 
127.0.0.1:6379> set key5 555
QUEUED
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get key4
(nil)
127.0.0.1:6379> get key5
(nil)
127.0.

前面不是说了 redis 事务中的操作出现了问题不是不会发生回滚吗?这里为什么事务中的操作都没有执行呢?其实对于 redis 事务是否回滚取决于错误发生的类型,如果发生错误的类型是编译时异常,也就是命令错误时,就会发生回滚,运行时异常则不会发生回滚:

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set key4 nihao
QUEUED
127.0.0.1:6379> INCR key4
QUEUED
127.0.0.1:6379> set key5 555
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
127.0.0.1:6379> get key4
"nihao"
127.0.0.1:6379> get key5
"555"

这里 key4 不是 intstr 类型,所以执行 INCR 自增的时候就会发生错误,但是由于这里的错误类型是运行时异常,所以事务就不会发生回滚。

然后看看丢失当前事务的操作:

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set key6 666
QUEUED
127.0.0.1:6379> set key7 777
QUEUED
127.0.0.1:6379> DISCARD
OK
127.0.0.1:6379> get key6
(nil)
127.0.0.1:6379> get key7
(nil)

这是 DISCARD 丢失事务的实现。如果在开启了事务,并且向服务器发送了若干命令之后,服务器突然重启了。服务器重启也就意味了内存中的数据都丢失了,那么事务对应的队列中的数据也就丢失了,这时候该怎么办呢?其实这时就相当于执行了 DISCARD 丢弃事务的操作。

WATCH UNWATCH实现乐观锁

假设在事务开始的过程,执行之前,其他客户端对数据进行了修改,而当前客户端事务中也会对这个数据进行修改,但是对于这个数据修改多次是不允许的,那么在开启事务之后,执行事务之前,如何判断在这个事务中要使用到的数据已经被修改了呢?

这就需要使用到 WATCH 命令和 UNWATCH 命令了。通过使用 WATCH key 就可以监视这个 key,当监视了这个 key 之后,如果在事务中需要修改这个 key 之前,这个 key 已经被修改了,那么事务就会相当于执行 DISCARD 命令,丢弃当前事务。

先开启事务,并向 redis 服务器发送几个命令,但是不执行,然后再开启一个窗口修改 watch 监视的key:

127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> set key1 111
OK
127.0.0.1:6379> WATCH key1
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set key1 333
QUEUED
127.0.0.1:6379> set key1 222
OK

执行事务:

127.0.0.1:6379> EXEC
(nil)
127.0.0.1:6379> get key1
"222"

可以看到 key1 最终的结果是另一个窗口修改的 key1 的值,另一个窗口修改的操作是早于当前窗口事务的修改的操作的,按理来说,key1 的值应该是事务中修改的 key1 的值,结果却相反,说明当前窗口的事务中的操作没有执行,事务被丢弃了。

使用 UNWATCH 可以接触 WATCH 对于 key 的监视。

这个 WATCH 命令就相当于我们前面学习多线程中的加乐观锁的操作,乐观锁假设在大多数情况下,多个线程或事务之间不会发生冲突,因此在读取数据时不会上锁。相反,乐观锁会在更新数据时判断在此期间数据是否被其他线程或事务修改过。

与乐观锁相对应的就是悲观锁,悲观锁总是假设最坏的情况,即认为数据在处理过程中总是会被其他线程或事务修改,因此在数据处理开始之前就先对数据进行锁定。

乐观锁相对于悲观锁更轻量。WATCH 的执行流程大概就是,在事务中,要修改监视的值时,先判断当前key的值是否和使用 WATCH key 监视key的时候的值相同,如果相同就允许修改,不同则 DISCARD。这样虽然可以,但是又会发生 ABA 问题,就是这个值被修改过了,只不过在我判断之前这个值又被改了回来,当出现这种情况的时候也是会出现问题的,所以 redis 的 WATCH 乐观锁的实现就是根据版本号来判断的,当使用 WATCH key 监视 key 的时候就会为这个 key 定义一个版本号,当对这个 key 进行修改的时候,版本号就会加上或者减去一个值(要加每次修改,版本号都是加,减,版本号则是减,不会出现这次修改,版本号变大,下次修改版本号变小的情况),所以通过版本号的操作就很好的解决了 ABA 问题。

WATCH 命令只针对于事务来说

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

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

相关文章

ArcGIS中分割与按属性分割的区别

1、分割ArcGIS批量导出各个市的县级行政边界 视频教学: ArcGIS批量导出各个市的县级行政边界002 2、ArcGIS批量导出全国各省的边界 视频教学: ArcGIS导出全国各省的边界003 推荐学习: ArcGIS全系列实战视频教程——9个单一课程组合系列直播回…

RAG技术综述

RAG的基本架构。,生成器和检索器。 参考paper:https://arxiv.org/html/2402.19473v4 文中将rag的内容从文本扩展至多模态,打开了思路。 生成器:transformer,LSTM,扩散模型,gan 检索器&#xf…

怎么一键消除路人?教你三个消除方法

怎么一键消除路人?在数字时代,摄影已成为我们记录生活、表达情感的重要方式。然而,完美的照片背后往往隐藏着一些不那么完美的元素——比如那些不经意间闯入镜头的路人。他们或许只是匆匆过客,但却足以破坏你精心构图的美好瞬间。…

香农信息量/自信息、信息熵、相对熵/KL散度/信息散度、交叉熵

诸神缄默不语-个人CSDN博文目录 文章目录 1. 引言2. 什么是熵?3. 香农信息量/自信息香农信息量的定义香农信息量的含义香农信息量计算示例香农信息量与信息熵的关系 4. 信息熵信息熵的定义信息熵的计算公式信息熵计算示例 5. 衡量两个分布间的差异:相对熵…

Excel工作簿/表的合并/拆分全集(一文通关)

概述 在工作中,我们常会用到到Excel拆分/合并为多个工作表/簿,如全国的订单表,需要根据省份列拆分下发至对应的省、各省份数据需要汇总、...... 应该如何操作呢? 1. 传统方法(借助透视表、Power Query编辑器、VBA实现…

Alienware外星人笔记本m17 R3原厂OEM预装Win10系统包下载,恢复开箱状态电脑自带系统

适用型号:Alienware M17 R3 链接:https://pan.baidu.com/s/1m3RwLmIlih3iPn5AclpptQ?pwdmsef 提取码:msef 外星人原装W10系统自带所有驱动、出厂专用主题壁纸、系统属性专属联机支持标志、系统属性专属LOGO标志、Office办公软件、MyAlie…

k8s-helloword部署一个应用

k8s-helloword部署一个应用 快速部署一个pod命令 部署一个名为 test-nginx Pod 方式一:使用 kubectl run kubectl run test-nginx --imagenginx然后使用 kubectl get pod 查看,kubectl get pod 是查看默认名称空间下的Pod 如果想要跟详细的查看这个…

OpenAI模型GPT-4o、GPT-4、Gemini 1.5性能比较

大家好,OpenAI最新推出的GPT-4o,标志着人工智能语言模型和交互方式迈入了新纪元。最引人注目的是,GPT-4o支持实时互动和流畅的对话切换,让交流更加自然。 本文将对比分析GPT-4o、GPT 4以及谷歌的Gemini和Unicorn模型,…

java继承使用细节二

构造器 主类是无参构造器时会默认调用 public graduate() {// TODO Auto-generated constructor stub也就是说我这里要用构造器会直接调用父类。它是默认看不到的 ,System.out.println("graduate");} 但当主类是有参构造器如 public father_(int s,doubl…

2024最新私有化部署AI大模型,让每个人都有属于自己的AI助理

让每个人都拥有一个属于自己的本地大模型 下载Ollama 下载地址 ​ https://ollama.com/download ​ Ollama支持MacOS、Linux、Windows 解压 下载完成后,会得到一个Ollama-darwin.zip文件,解压后,以Mac为例是一个可运行文件:O…

鸿蒙HarmonyOS开发:tabs结合tabContent实现底部tabBar导航栏页面布局

文章目录 一、组件介绍1、Tabs参数属性事件TabsController 2、子组件属性说明 二、基础示例1、基础顶部导航2、效果3、可以滚动导航栏2、效果 三、扩展示例自定义导航栏1、代码2、效果 一、组件介绍 Tabs组件的页面组成包含两个部分,分别是TabContent和TabBar。Tab…

【CTF Web】NSSCTF 3868 [LitCTF 2023]这是什么?SQL !注一下 !Writeup(SQL注入+报错注入+括号闭合+DIOS)

[LitCTF 2023]这是什么?SQL !注一下 ! 为了安全起见多带了几个套罢了o(▽)q 出题人 探姬 解法 先试试这个: )))))) or 11 -- 有结果了,但是这个 flag 是假的。 flag 可能在其他表里。用 hackbar 上 DIOS payload。 …

2024-2030数据集成成熟度曲线(一)

作者 | 郭炜 导读:最新发布的《技术成熟度曲线2024》全面评估数据集成技术架构的7个维度,包括技术成熟度、技术难度、业务价值、技术成熟周期、管理协作难度、大模型结合等评估维度,报告篇幅较长,我们将报告分为3篇系列文章&#…

微信小程序源码-基于Java后端的会议发布与预约系统毕业设计(附源码+演示录像+LW)

大家好!我是程序员一帆,感谢您阅读本文,欢迎一键三连哦。 💞当前专栏:微信小程序毕业设计 精彩专栏推荐👇🏻👇🏻👇🏻 🎀 Python毕业设…

一文通晓mysql

目录 1.mysql在centos7环境上的安装 2.数据库基础 1. 什么是数据库 2.基本认识 3.库的操作 1.创建数据库 2.查看数据库列表 3.删除数据库 4.修改数据库 5.库的备份与修复 4.表的操作 1.创建表 2.查看表 3.修改表 修改表名 给表增加属性。 修改表中的某个属性&…

【传知代码】用二维图像渲染3D场景视频-论文复现

文章目录 概述原理介绍模型介绍环境配置/部署方式安装环境准备数据训练(train)评估(eval)渲染(render) 小结 论文地址 本文涉及的源码可从用二维图像渲染3D场景视频该文章下方附件获取 概述 **NeRF&#…

第十九届全国环境友好科技竞赛(绿色创业类)正式启动

近日,第十九届全国环境友好科技竞赛(绿色创业类)正式拉开帷幕。本次竞赛由清华大学、同济大学、西安建筑科技大学及中国环境科学学会共同主办,旨在通过学科竞赛的方式鼓励全国高校学生积极参与到资源节约型和环境友好型的和谐社会…

【linux-IMX6ULL-LED字符驱动框架完善】

目录 1.简介2.前置知识2.1 重要函数及结构体2.2 程序框架流程 3. 代码详解: 1.简介 在上节,我对linux-IMX6ULL-字符设备驱动简单框架实验进行了说明和构建,但是也存在几个问题; 需要手动指定设备号,不能自…

Android Studio添加依赖 新版 和 旧版 的添加方式(Gradle添加依赖)(Java)

旧版的(在线添加) 1找 文件 在项目的build.gradle文件中添加依赖(在下面的节点中添加库 格式 ’ 组 :名字 : 版本号 ‘ ) dependencies {implementation com.example:library:1.0.0 }implementation 组:名字:版本…

手机版AI写作软件哪个好用?5款AI写作软件分享

在这个快节凑的时代,人们对于高效、便捷的创作方式很是追求。尤其是在人工智能技术发展迅速的今天,AI写作软件的出现,让很多自媒体创作者都会想到在手机上面进内容创作,这样不仅能提高工作效率,而且工作的自由度会更高…