Redis 事务机制深入浅出
笔者事务相关文章链接:Redis WATCH事务监视机制与回滚
什么是Redis事务
Redis的事务就是一组命令的集合。Redis提供了将一组命令打包集合的方法,并且能够一次性、按顺序的执行多个命令,事务执行期间,服务器不会中断事务改为执行其他客户端的命令请求,只有事务中所有命令都执行完毕后,服务器才会处理其他客户端的命令请求。
在开始说明事务的使用与基本流程之前,需要先说明关于Redis和事务的两个问题。
Redis事务具有原子性吗?
先给出结论:Redis单条命令具有原子性,Redis事务是否具有原子性存在争议。
笔者认为关于Redis事务原子性的争议存在的主要原因是对原子性定义不统一。
关于原子性的定义,首先操作不能被中断是公认的必要条件,分歧的点在于,一说认为操作要么全部执行,要么全部不执行才能说操作具有原子性,另一说认为操作要么全部执行成功,要么全部执行失败才能说操作具有原子性。
在关系型数据库中,原子性体现在要么事务中的命令全部成功执行,要么全部不执行,事务中任一命令出现错误,会回滚此前已经执行了的命令。
在Redis中,只能保证事务不可中断,但若事务执行过程中某条命令出现错误,Redis不会回滚已经执行了的命令,因此Redis只做到了要么不执行,要么全部执行,但不能保证出现事务内命令错误时全部执行失败。
因此,无论是哪种对于原子性的理解,关系型数据库中的事务都满足,即关系型数据库中事务是具有原子性的。如果认同前者原子性定义(要么全做,要么全不做),那么可以说Redis的事务具有原子性,如果认同后者的原子性定义(要么全成功,要么全失败),那么Redis的事务不具有原子性
Redis支持回滚吗?
在Redis官方文档中明确指出,Redis不支持回滚。
笔者在浏览其余关于Redis回滚问题的博文时,发现部分文章内提及,使用WATCH关键字监控事务时,发现被监控的数据库键被修改时,会进行回滚。产生这种误解是由于没有理解WATCH的判断时机,WATCH早在事务将要实际执行前就会进行判断,若被监控的数据库键被修改,整个事务都不会执行,而非执行到具体被监控的数据库键操作时才进行判断。
事务的执行流程
事务从开始到结束共经历三个阶段:
- 事务开始
- 命令入队
- 事务执行
事务开始
首先明确一点,底层实现中每个Redis客户端内都有一个用于标识事务状态的属性。
Redis中,使用MULTI
命令来开启一个事务,命令执行时会判断当前客户端的事务状态,如果当前客户端事务状态已经开启,返回错误并提示事务不可嵌套,若客户端事务未开启,则修改客户端状态开启并返回OK。
演示如下:
127.0.0.1:6379> multi
OK
127.0.0.1:6379> multi
(error) ERR MULTI calls can not be nested
命令入队
同样,Redis每一条命令执行前都会判断客户端事务标识状态,如果事务没有开启,命令自然直接执行,事务开开启时,不会执行执行命令,会将命令入队。
演示如下:
127.0.0.1:6379> set a 1
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set a 2
QUEUED
命令执行
使用EXEC
命令来执行当前事务,事务内的命令会按照入队顺序依次执行,事务执行完毕或执行失败时会改变当前客户端事务标识状态,事务未开启时使用EXEC
命令会报错。
完整演示如下:
127.0.0.1:6379> set a 1
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set b 1
QUEUED
127.0.0.1:6379> incr a
QUEUED
127.0.0.1:6379> exec
1) OK
2) (integer) 2
127.0.0.1:6379> exec
(error) ERR EXEC without MULTI
放弃事务
Redis提供了DISCARD
命令来放弃当前事务,成功放弃事务时返回OK,事务为未开启状态时返回错误。
演示如下:
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set a 1
QUEUED
127.0.0.1:6379> discard
OK
127.0.0.1:6379> exec
(error) ERR EXEC without MULTI
事务对于错误的处理
Redis事务有两种可能的错误
命令入队时错误
第一种可能的情况是在命令入队阶段,键入了错误的命令,Redis事务对此的处理是弃置整个事务。
演示如下:
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set a 1
QUEUED
127.0.0.1:6379> abc
(error) ERR unknown command `abc`, with args beginning with:
127.0.0.1:6379> set b 1
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> mget a b
1) (nil)
2) (nil)
由以上演示可见,事务内包含错误命令时,会直接弃用整个事务,提示信息为由于此前(命令入队)的错误,已经放弃执行事务。
命令执行时错误
第二种可能的错误是,事务内的命令格式全部正确,但执行时出现错误,比如incr自增的对象不能被转换为整数,对于此种情况,Redis的处理是,事务内任一命令的执行错误不会影响其它命令的正常执行,更不存在事务回滚这一操作。
演示如下:
127.0.0.1:6379> set a 1
OK
127.0.0.1:6379> set b string
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr a
QUEUED
127.0.0.1:6379> incr b
QUEUED
127.0.0.1:6379> exec
1) (integer) 2
2) (error) ERR value is not an integer or out of range
127.0.0.1:6379> mget a b
1) "2"
2) "string"
总结
事务流程
流程图总结如下:
Redis事务的ACID性质
原子性
基本同文首解释的相同,不过多赘述。
首先Redis的事务一定能保证执行不会被中断。但Redis只能保证事务内命令要么全部执行,要么全部不执行,不能保证全部执行成功或全部执行失败,Redis事务是否具有原子性存在争议。
一致性
Redis能够保证,Redis事务在开始前和结束后数据库的完整性不会被破坏,因此Redis事务具有一致性。
隔离性
Redis能够保证,当数据库中有多客户端同时执行事务时(并发),各事务间不会互相影响,在并发状态下执行的事务和串行时执行事务的结果完全相同,Redis事务具有隔离性。
持久性
Redis事务本身没有持久化的操作,但如果服务器开启了AOF或者RDB的持久化,可以认为Redis事务具有持久性。
Redis 事务机制深入浅出相关推荐
- Redis事务机制 -Redis 核心技术与实战
事务是数据库的一个重要功能.所谓的事务,就是指对数据进行读写的一系列操作.事务在执行时,会提供专门的属性保证,包括` 原子性(Atomicity) 一致性(Consistency) 隔离性(Isola ...
- redis 学习 --->>> 9、Redis 事务机制
9.Redis 事务机制 1.事务的定义 Redis 事务是一个单独的隔离操作: 事务中的所有命令都会序列化.按顺序地执行.事务在执行的过程中,不会被其他客户端发送来的命令请求所打断. Redis事务 ...
- 16-SpringBoot之Redis(三)——Redis事务机制
SpringBoot之Redis(三)--Redis事务机制 1. Redis 事务执行过程 2. 开启事务支持 3. 测试 4. 测试结果说明 5. 源码下载 1. Redis 事务执行过程 Red ...
- Redis事务机制和分布式锁
Redis事务机制 严格意义来讲,Redis的事务和我们理解的传统数据库(如mysql)的事务是不一样的:Redis的事务实质上是命令的集合,在一个事务中要么所有命令都被执行,要么所有事物都不执行. ...
- 图解Redis事务机制
来自:Java中文社群 作为关系型数据库中一项非常重要的基础功能--事务,在 Redis 中是如何处理并使用的? 1.前言 事务指的是提供一种将多个命令打包,一次性按顺序地执行的机制,并且保证服务器只 ...
- Redis学习笔记~Redis事务机制与Lind.DDD.Repositories.Redis事务机制的实现
回到目录 Redis本身支持事务,这就是SQL数据库有Transaction一样,而Redis的驱动也支持事务,这在ServiceStack.Redis就有所体现,它也是目前最受业界认可的Redis驱 ...
- Redis实战 - 15 Redis事务机制和乐观锁实现
文章目录 1. Redis事务简介 2. Redis事务的操作命令 3. Redis的事务回滚 4. Redis监控事务 1. Redis事务简介 在 Redis 中,也存在多个客户端同时向 Redi ...
- java redis事务机制_Redis 事务机制
Redis 事务:可以一次执行多个命令,本质是一组命令的集合.一个事务中的所有命令都会序列化,按顺序串行化执行而不会被其它命令插入,一次性.顺序性.排他性的执行一系列命令. 一.常用命令 [1] :开 ...
- Redis 事务机制实现
1.首先,我们来看一下Redis中事物相关的指令, 命令原型 命令描述 MULTI 用于标记事务的开始,其后执行的命令都将被存入命令队列,直到执行EXEC时,这些命令才会被原子执行. ...
最新文章
- 自动分析源代码,创建函数地图展示调用关系
- Python 进程之间共享数据(全局变量)
- 架构设计贵在务实(转载)
- register_chrdev深入分析
- OpenLDAP / Ubuntu 18.04 下 docker 版安装
- python子进程关闭fd_如果创建了multiprocessing.Pool,Python子进程wait()将失败
- mondrain配置mysql_mondrian 4.7 源码部署(示例代码)
- Bootstrap(二)—格栅系统!
- Unreal Engine 4 编码规范
- 国产“电动牦牛”亮相,负重 160 公斤健步如飞!
- flask框架(四):通过局域网访问网站
- 【CSS】解决图片和盒子底部产生的缝隙问题
- 基于阈值和深度学习的玉米常见锈病严重程度自动模糊逻辑预测(工具+综述+玉米锈病严重程度数据集)
- python打乱列表的方法_python打乱列表
- php调用文章至首页,WP如何在首页调用分类文章列表的详细教程
- 关于DatetTime?
- 动态添加GRIDVIEW内容 和数据绑定
- 熊迈摄像头SDK二次开发:登录、截屏、录像等功能
- 【云游戏】云游戏的架构设计和技术实现
- Input用户输入完后再执行方法