Redis中的事务(二)

事务

一个完整的WATCH事务执行过程

假设当前服务端为c10086,而数据库watched_keys字典的当前状态如图所示,那么当c10086执行以下WATCH命令之后

c10086> WATCH "name"
OK

watched_keys字典将更新如图所示的状态。接下来客户端c10086继续向服务器发送MULTI命令,并将一个SET命令放入
事务队列:

c10086> MULTI
OK

c10086> SET "name" "peter"
QUEUED

就在这时,另一个客户端c999向服务器发送了一条SET命令,将"name"键的值设置成了"john":

c999>SET "name" "john"
OK

c999执行的这个SET命令会导致正在监视"name"键的所有客户端的REDIS_DIRTY_CAS标识被打开,其中包括客户端c10086.
之后,当c10086向服务器发送EXEC命令的时候,因为c10086的REDIS_DIRTY_CAS标志已经被打开,所以服务器将拒绝执行
它提交的事务:

c10086>EXEC
(nil)

在这里插入图片描述
在这里插入图片描述

事务的ACID性质。

在传统的关系式数据库中,常常用ACID性质来检验事务功能的可靠性和安全性。在Redis中,事务总是具有原子性(Atomicity)、一致性(Consistency)和隔离性(Isolation),并且当Redis运行在某种特定的持久化模式下,事务也具有耐久性(Durability)

原子性

事务具有原子性指的是,数据库将事务中的多个操作当作一个整体来执行,服务器要么就执行事务中的所有操作,要么就一个操作也不执行。对于Redis的事务功能来说,事务队列中的命令要么就全部都执行,要么就一个都不执行,因此,Redis的事务是具有原子性的。

Redis的事务和传统的关系型数据库事务的最大区别在于,Redis不支持事务回滚机制(rollback),即使事务队列中的某个命令在执行期间出现了错误,整个事务也会继续执行下去,直到将事务队列中的所有命令都执行完毕为止

例子
  • 举个例子。以下展示了一个成功执行的事务,事务中的所有命令都会被执行
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET msg "hello"
QUEUED
127.0.0.1:6379> GET msg
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) "hello"
  • 举个例子。与此相反,以下展示了一个执行失败的事务,这个事务因为命令入队出错而被服务器拒绝执行,事务中的所有命令都不会被执行:
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET msg "hello"
QUEUED
127.0.0.1:6379> GET
(error) ERR wrong number of arguments for 'get' command
127.0.0.1:6379> GET msg
QUEUED
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
  • 举个例子。在下面的例子中,即使RPUSH命令在执行期间出现了错误,事务的后续命令也会继续执行下去,并且之前执行的命令也不会有任何影响
127.0.0.1:6379> SET msg "hello"
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SADD fruit "apple" "banana" "cherry"
QUEUED
127.0.0.1:6379> RPUSH msg "good bye" " bye bye"
QUEUED
127.0.0.1:6379> SADD alphabet "a" "b" "c"
QUEUED
127.0.0.1:6379> EXEC
1) (integer) 3
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) (integer) 3
127.0.0.1:6379> SCARD fruit
(integer) 3

Redis的作者在事务功能的文档中解释说,不支持事务回滚是因为这种复杂的功能和Redis追求简单高效的设计主旨不相符,并且他认为,Redis的事务的执行时错误通常都是编程错误产生的,这种错误通常只会出现在开发环境中,而很少会在实际的生产环境中出现,所以他认为没有必要为Redis开发事务回滚功能

一致性

事务具有一致性指的是,如果数据库在执行事务之前是一致的,那么在事务执行之后,无论事务是否执行成功,数据库也仍然是一致的。"一致"指的是数据符合数据库本身的定义和要求,没有包含非法或者无效的错误数据。Redis通过谨慎的错误检测和简单的设计来保证事务的一致性

入队错误

如果一个事务在入队命令的过程中,出现了命令不存在,或者命令的格式不正确等情况,那么Redis将拒绝执行这个事务。在以下的示例中,因为客户端尝试向事务入队一个不存在的命令YAHOOOO,所以客户端提交的事务会被服务器拒绝执行:

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET msg "hello"
QUEUED
127.0.0.1:6379> YAHOOOO
(error) ERR unknown command 'YAHOOOO'
127.0.0.1:6379> GET msg
QUEUED
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.

因为服务器会拒绝执行入队过程中出现错误的事务,所以Redis事务的一致性不会被带有入队错误的事务影响。

Redis2.6.5以前的入队错误处理

在Redis2.6.5以前的版本,即使有命令在入队过程中发生了错误,事务一样可以执行,不过被执行的命令只包括那些正确入队的命令。以下代码是在Redis2.6.4版本上测试的,可以看到,事务可以正常执行,但只有成功入队的SET命令和GET命令被执行了,而错误的YAHOOOO则被忽略了

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET msg "hello"
QUEUED
127.0.0.1:6379> YAHOOOO
(error) ERR unknown command 'YAHOOOO'
127.0.0.1:6379> GET msg
QUEUED
127.0.0.1:6379> EXEC
1).OK
2)."hello"

因为错误的命令不会被入队,所以Redis不会尝试去执行错误的命令,因此,即使在2.6.5以前的版本中,Redis事务的一致性也不会被入队错误影响

执行错误

除了入队时可能发生错误以外,事务还可能在执行的过程中发生错误。关于这种错误有两个需要说明的地方:

  • 1.执行过程中发生的错误都是一些不能入队时被服务器发现的错误,这些错误只会在命令实际执行时被触发
  • 2.即使在事务的执行过程中发生了错误,服务器也不会中断事务的执行,它会继续执行事务中余下的其他命令,并且已执行的命令(包括执行命令所产生的结果)不会被出错的命令影响对数据库键执行了错误类型的操作是事务执行期间最常见的错误之一。
    在下面的示例中,首先用SET命令将键"msg"设置成了一个字符串键,然后在事务里面尝试对"msg"键执行只能用于列表键的RPUSH命令,这将引发一个错误,并且这种错误只能在事务执行(也即是命令执行)期间被发现:
127.0.0.1:6379> SET msg "hello"
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SADD fruit "apple" "banana" "cherry"
QUEUED
127.0.0.1:6379> RPUSH msg "good bye" " bye bye"
QUEUED
127.0.0.1:6379> SADD alphabet "a" "b" "c"
QUEUED
127.0.0.1:6379> EXEC
1) (integer) 3
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) (integer) 3

因为在事务执行的过程中,出错的命令会被服务器识别出来,并进行相应的错误处理,所以这些出错命令不会对数据库做任何修改,也不会对事务的已执行产生影响

服务器停机

如果Redis服务器在执行事务的过程中停机,那么根据服务器所使用的持久化模式,可能有以下情况出现:

  • 1.如果服务器运行在无持久化的内存模式下,那么重启之后的数据库将是空白的,因此数据总是一致的。
  • 2.如果服务器运行在RDB模式下,那么在事务中途停机不会导致不一致性,因为服务器可以根据现有的RDB文件来恢复数据,从而将数据库还原到一个一致的状态。如果找不到可供使用的RDB文件,那么重启之后的
    数据库将是空白的,而空白数据库总是一致的
  • 3.如果服务器运行在AOF模式下,那么在事务中途停机不会导致不一致性,因为服务器可以根据现有的AOF文件,从而将数据库还原到一个一致的状态。如果找不到可供使用的AOF文件,那么重启之后的数据库将是
    空白的,而空白数据库总是一致的。综上所述,无论Redis服务器运行在哪种持久化模式下,事务执行中途发生的停机都不会影响数据库的一致性

隔离性

事务的隔离性指的是,即使数据库中有多个事务并发地执行,各个事务之间也不会互相影响,并且在并发状态下执行的事务和串行执行的事务产生的结果完全相同。因为Redis使用单线程的方式来执行事务(以及事务
队列中的命令),并且服务器保证在执行事务期间不会对事务进行中断,因此,Redis的事务总是以串行的方式运行的。并且事务也总是具有隔离性

耐久性

事务的耐久性指的是,当一个事务执行完毕时,执行这个事务所得的结果已经被保存到永久性存储介质(比如硬盘)里面了,即使服务器在事务执行完毕之后停机,执行事务所得的结果也不会丢失。因为Redis的事务不过是简单地使用队列包裹起了一组Redis命令,Redis并没有为事务提供任何额外的持久化功能,所以Redis事务的耐久性由Redis所使用的持久化模式决定:

  • 1.当服务器在无持久化的内存模式下运作时,事务不具有耐久性:一旦服务器停机,包括事务数据在内的所有服务器数据都将丢失
  • 2.当服务器在RDB持久化模式下运作时,服务器只会在特定的保存条件被满足时才会执行BGSAVE命令,对数据库进行保存操作,并且异步执行的BGSAVE不能保证事务数据第一时间保存到硬盘里面,因此RDB持久化模式下的事务也不具有耐久性
  • 3.当服务器运行在AOF持久化模式下,并且appendfsync选项的值为everysec时,程序会每秒同步一次命令数据到硬盘,因为停机可能恰好发生在等待同步的那一秒钟之内,这可能会造成事务数据丢失,所以这种配置下的事务不具有耐久性
  • 4.当服务器运行在AOF持久化模式下,并且apendfsync选项的值为no时,程序会交由操作系统来决定何时将命令数据同步到硬盘。因为事务数据可能在等待同步的过程中丢失,所以这种配置下的事务不具有耐久性

不论Redis在什么模式下运作,在一个事务的最后加上SAVE命令总可以保证事务的耐久性:

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET msg "hello"
QUEUED
127.0.0.1:6379> SAVE
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) OK

不过这种做法的效率太低,所以不具有实用性

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[2021最新]Java时间戳和日期时间互转换

代码: import java.text.ParseException; import java.text.SimpleDateFormat;public class MainProcess {public static void main(String[] args) throws ParseException {// 1.set formatSimpleDateFormat timeSmat new SimpleDateFormat("yyyy-MM-dd HH:…

Kubernetes中安装部署ActiveMQ集群(手把手式记录)

目录 1、创建命名空间 nacos-cluster 2、配置文件准备 2.1 activemq0.xml 2.2 activemq1.xml 2.3 activemq2.xml 3、创建configMap cm-activemq 4、创建activemq-cluster.yaml 5、执行命令部署 6、部署成功,查看结果 这里以3个borker的集群为例&#xff0…

Facade 外观

意图 为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一字系统更加容易使用。 结构 其中: Facade知道哪些子系统负责处理请求;将客户的请求代理给适当的子系统对象。 Subsystem classes…

QGIS插件Geo-SAM使用(基于SAM半自动标注遥感图像)

0.Geo-SAM介绍 Geo-SAM是一个QGIS插件,旨在帮助人们在使用大尺寸地理空间栅格图像时有效地分割、描绘或标记地貌。Segment Anything Model (SAM) 是一个具有超能力的基础 AI 模型,但模型大小巨大,即使使用现代 GPU&am…

C++学习进阶版(一):用C++写简单的状态机实现

目录 一、基础知识 1、状态机 2、四大要素 3、描述方式 4、设计步骤 5、实现过程中需注意 (1) 状态定义 (2) 状态转换规则 (3) 输入处理 (4) 状态机的封装 (5…

Nginx第2篇-HTTPS配置教程

背景 我最近做个项目要上线,接口部署到服务器,总不能给别人个ip地址加端口吧,而且小程序上线要有接口不能是ip和http协议,必须是https协议。这里记录下使用Nginx配置HTTPS的过程,主要包含以下三部分。 申请域名SSL证…

远程预付费集抄管理系统

远程预付费集抄管理系统是一种用于能源(如水、电等)预付费管理的智能化系统,其核心在于提供远程集中抄表和费用管理服务。这种系统通过集成先进的远程监控技术和预付费管理功能,为用户提供了便捷的能源管理解决方案。下文将从核心功能、工作流程、优势特…

离世界模型更近一步!Meta开源OpenEQA,评估AI Agent情景理解能力

Yann LeCun 朝着 “世界模型” 又近了一步。 Meta最新的开源工作OpenEQA:从文字模型到世界模型,可以像人一样记忆、推理的新基准,AI理解物理空间又近了一步。 场景1: 假设你正准备离开家,但找不到你的工牌。 现在,…

5.2 iHRM人力资源 - 员工管理 - 使用文件导入导出员工

iHRM人力资源 - 员工管理 - 导入导出员工 文章目录 iHRM人力资源 - 员工管理 - 导入导出员工一、员工导出Excel二、员工导入Excel2.1 Excel导入组件封装2.2 下载导入模板2.3 Excel 导入功能 三、删除员工 一、员工导出Excel 这个地方涉及一个接口二进制流blob 就是下面这一大片…

使用嘉立创EDA打开JSON格式的PCB及原理图

一、将PCB和原理图放同一文件夹 并打包成.zip文件 二、打开嘉立创EDA并导入.zip文件 文件 -> 导入 -> 嘉立创EDA标准版/专业版 三、选择.zip文件并选择 “导入文件并提取库” 四、自定义工程路径 完成导入并转换为.eprj文件 五、视频教学 bilibili_使用立创EDA打开JSO…

香港科技大学广州|数据科学与分析学域硕博招生宣讲会—华东师范大学专场

时间:2024年4月25日(星期四)13:30 地点:华东师范大学普陀校区文附楼507 报名链接:https://www.wjx.top/vm/Q0cKTUI.aspx# 跨学科研究领域 *数据驱动的人工智能和机器学习 *统计学习和建模 工业和商业分析 *特定行业…

float实现文字环绕效果

实现效果如下: 一、问题分析 接到需求就是右侧显示图片,左侧显示一个标题和内容。第一时间没有想到其他的布局的好的实现方式,就想到了float布局。于是乎去查了下有关float的文档,float 是相当的好用。 float定义如下&#xf…

kibana源码编译

一、安装nodejs16.14.2及yarn (一)nodejs 1、下载 https://cdn.npmmirror.com/binaries/node/v16.14.2/node-v16.14.2-linux-x64.tar.gz2、解压 tar -zxf node-v16.14.2-linux-x64.tar.gz -C /app cd /app mv node-v16.14.2-linux-x64 node3、配置环…

在Linux系统中设定延迟任务

一、在系统中设定延迟任务要求如下: 要求: 在系统中建立easylee用户,设定其密码为easylee 延迟任务由root用户建立 要求在5小时后备份系统中的用户信息文件到/backup中 确保延迟任务是使用非交互模式建立 确保系统中只有root用户和easylee用户…

Matlab|基于改进遗传算法的配电网故障定位

目录 1 主要内容 2 部分代码 3 部分程序结果 4 下载链接 1 主要内容 该程序复现文章《基于改进遗传算法的配电网故障定位》,将改进的遗传算法应用于配电网故障定位中, 并引入分级处理思想, 利用配电网呈辐射状的特点, 首先把整个配电网划分为主干支路和若干独立…

2024年阿里云4核8G配置云服务器价格低性能高!

阿里云4核8G服务器租用优惠价格700元1年,配置为ECS通用算力型u1实例(ecs.u1-c1m2.xlarge)4核8G配置、1M到3M带宽可选、ESSD Entry系统盘20G到40G可选,CPU采用Intel(R) Xeon(R) Platinum处理器,阿里云优惠 aliyunfuwuqi…

【Python】高级进阶(专版提升3)

Python 1 程序结构1.1 模块 Module1.1.1 定义1.1.2 作用1.1.3 导入1.1.3.1 import1.1.3.2 from import 1.1.4 模块变量1.1.5 加载过程1.1.6 分类 1.2 包package1.2.1 定义1.2.2 作用1.2.3 导入1.1.3.1 import1.1.3.2 from import 2 异常处理Error2.1 异常2.2 处理 3 迭代3.1 可…

TinyEMU源码分析之访存处理

TinyEMU源码分析之访存处理 1 访存指令介绍2 指令译码3 地址转换3.1 VA与PA3.2 VA转PA 4 判断地址空间范围5 执行访存操作5.1 访问RAM内存5.2 访问非RAM(设备)内存 6 访存处理流程图 本文属于《 TinyEMU模拟器基础系列教程》之一,欢迎查看其…

数据结构排序算法

排序也称排序算法(SortAlgorithm),排序是将一组数据,依指定的顺序进行排列的过程。 分类 内部排序【使用内存】 指将需要处理的所有数据都加载到内部存储器中进行排序插入排序 直接插入排序希尔排序 选择排序 简单选择排序堆排序 交换排序 冒泡排序快速…

两阶段提交进阶

两阶段提交之进阶 上一节我们讲了,两阶段提交逻辑上的表现,其实较为肤浅,并且偏向理论,可能大家都能看懂,但是如果放入实际的mysql应用中并联系事务和日志进行分析,又会怎么样呢? 这次就专门分…