三、redis系列之事务
1. 绪言
Redis也提供了事务机制,可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其他命令插入,不许加塞。但Redis对事务的支持是部分支持,不想关系型数据库,要么都成功要么都失败,Redis可以部分成功部分失败。本篇中,我们来详细所以说redis那些事。
2. Redis事务机制
2.1 事务流程
Redis中的事务(transaction)是一组命令的集合。事务同命令一样都是Redis最小的执行单位,一个事务中的命令要么都执行,要么都不执行,要么都成功,要么都失败。Redis事务的实现需要用到 MULTI 和 EXEC 两个命令,事务开始的时候先向Redis服务器发送 MULTI 命令,然后依次发送需要在本次事务中处理的命令,最后再发送 EXEC 命令表示事务命令结束。一个事务从开始到执行会经历以下三个阶段:
1)开始事务;
2)命令入队;
3)执行事务。
从上图输出中可以看到,当输入MULTI命令后,服务器返回OK表示事务开始成功,然后依次输入需要在本次事务中执行的所有命令,每次输入一个命令服务器并不会马上执行,而是返回”QUEUED”,这表示命令已经被服务器接受并且暂时保存起来,最后输入EXEC命令后,本次事务中的所有命令才会被依次执行,可以看到最后服务器一次性返回了三个OK,这里返回的结果与发送的命令是按顺序一一对应的,这说明这次事务中的命令全都执行成功了。
2.2 事务命令
在上一小节中,我们使用了MULTI命令和EXEC命令。MULTI命令标志着事务的开始,EXEC命令开始执行事务。从上一小节图片中我们也可以看出,事务中的命令要全部执行完之后才能获取每个命令的结果,但是如果一个事务中的命令B依赖于他上一个命令A的结果的话该怎么办呢?例如电商系统在抢购业务中,先要获取当前库存,才能在当前库存的基础上进行其他操作。这种场合仅仅使用上面介绍的MULTI和EXEC是不能实现的,因为MULTI和EXEC中的命令是一起执行的,并不能将其中一条命令的执行结果作为另一条命令的执行参数。这时候就要用到redis事务机制中的其他命令,下面列出了redis事务机制中所有命令:
命令原型 |
时间复杂度 |
命令描述 |
返回值 |
MULTI |
用于标记事务的开始,其后执行的命令都将被存入命令队列,直到执行EXEC时,这些命令才会被原子的执行。 |
始终返回OK |
|
EXEC |
执行在一个事务内命令队列中的所有命令,同时将当前连接的状态恢复为正常状态,即非事务状态。如果在事务中执行了WATCH命令,那么只有当WATCH所监控的Keys没有被修改的前提下,EXEC命令才能执行事务队列中的所有命令,否则EXEC将放弃当前事务中的所有命令。 |
原子性的返回事务中各条命令的返回结果。如果在事务中使用了WATCH,一旦事务被放弃,EXEC将返回NULL-multi-bulk回复。 |
|
DISCARD |
回滚事务队列中的所有命令,同时再将当前连接的状态恢复为正常状态,即非事务状态。如果WATCH命令被使用,该命令将UNWATCH所有的Keys。 |
始终返回OK。 |
|
WATCH key [key ...] |
O(1) |
在MULTI命令执行之前,可以指定待监控的Keys,然而在执行EXEC之前,如果被监控的Keys发生修改,EXEC将放弃执行该事务队列中的所有命令。 |
始终返回OK。 |
UNWATCH |
O(1) |
取消当前事务中指定监控的Keys,如果执行了EXEC或DISCARD命令,则无需再手工执行该命令了,因为在此之后,事务中所有被监控的Keys都将自动取消。 |
始终返回OK。 |
下面通过代码尝试使用上述几个命令:
1)正常执行
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> SET key01 a QUEUED 127.0.0.1:6379> SET key02 b QUEUED 127.0.0.1:6379> GET key01 QUEUED 127.0.0.1:6379> SET key03 c QUEUED 127.0.0.1:6379> EXEC 1) OK 2) OK 3) "a" 4) OK
2) 取消事务
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> SET key01 a QUEUED 127.0.0.1:6379> SET key02 b QUEUED 127.0.0.1:6379> DISCARD OK 127.0.0.1:6379> GET key01 (nil)
可以看到,执行DISCARD命令后,返回了OK,事务被取消,所以再次GET key01的时候返回了nil。
3)WATCH
命令按图示箭头方向顺序输入并执行,在左侧窗口中用WATCH命令监视key01,然后MULTI命令开始后,在右侧窗口更改了key02的值,所以左侧窗口执行EXEC命令后,返回nil,事务执行失败,事务中的INCR key01 , SET key02 1两条命令都没有执行,所以最后获取key02返回的值是nil,而key01的值也是右侧窗口的赋值。
4)UNWATCH
按图示箭头顺序输入并执行命令,WATCH监视key01后,用UNWATCH接触监视,开始MULTI事务后,在右侧窗口改变key01的值,然后左侧窗口继续执行事务,发现事务正常执行,事务中获取到的key01的值是在右侧窗口赋值的基础上加1,key02也成功创建。
2.3 Redis事务中的错误
先来看如下两块代码:
代码一:
在上述代码块中,先给key01赋一个字符串值,然后在事务中进行整数运算,显然是有误的,但是整个事务除了数值运算那个命令其他命令都成功运行。
代码块二:
在上述代码块中,事务中出现拼写错误,执行事务后,直接提示失败,没有任何返回值,可以发现,事务中所有命令都没有执行。
对比上述两个代码块,为什么一个事务成功执行,一个事务执行失败呢?这就涉及到redis事务中的两类失败:
1)运行错误: 运行错误表示命令在执行过程中出现错误,比如用GET命令获取一个散列表类型的键值、对字符型进行数字运算等。这种错误在命令执行之前Redis是无法发现的,所以在事务里这样的命令会被Redis接受并执行。如果事务里有一条命令执行错误,其他命令依旧会执行(包括出错之后的命令)。
2)语法错误:就像上面的例子一样,语法错误表示命令不存在或者参数错误例如参数的数量错误、命令名称错误,这种情况需要区分Redis的版本,Redis 2.6.5之前的版本会忽略错误的命令,执行其他正确的命令,2.6.5之后的版本会忽略这个事务中的所有命令,都不执行,就比如上面的例子。这种错误会导致事务执行失败,事务中所有命令都执行失败。
3. 总结
本篇介绍了redis中的事务机制,但关于分布式锁的部分并未涉及,之后再补充。
参考:
https://www.cnblogs.com/Jason-Xiang/p/5364252.html
https://blog.csdn.net/qq_37169817/article/details/78839774
三、redis系列之事务的更多相关文章
- Redis系列之key操作命令与Redis中的事务详解(六)
序言 本篇主要目的有二: 1.展示所有数据类型中key的所有操作命令,以供大家学习,查阅,更深入的挖掘redis潜力. 2.掌握redis中的事务,让你的数据完整性一致性拥有更优的保障. redis命 ...
- Redis系列二之事务及消息通知
一.事务 Redis中的事务是一组命令的集合.一个事务中的命令要么都执行,要么都不执行. 1.事务简介 事务的原理是先将一个事务的命令发送给Redis,然后再让Redis依次执行这些命令.下面看一个示 ...
- 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存
原文:http://blog.csdn.net/heyewu4107/article/details/71009712 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问 ...
- Redis系列(三):Redis集群的水平扩展与伸缩
一.Redis集群的水平扩展 Redis3.0版本以后,有了集群的功能,提供了比之前版本的哨兵模式更高的性能与可用性,但是集群的水平扩展却比较麻烦,接下来介绍下Redis高可用集群如何做水平扩展,在原 ...
- Redis系列(三):Redis的持久化机制(RDB、AOF)
本篇博客是Redis系列的第3篇,主要讲解下Redis的2种持久化机制:RDB和AOF. 本系列的前2篇可以点击以下链接查看: Redis系列(一):Redis简介及环境安装. Redis系列(二): ...
- redis系列:redis介绍与安装
前言 这个redis系列的文章将会记录博主学习redis的过程.基本上现在的互联网公司都会用到redis,所以学习这门技术于你于我都是有帮助的. 博主在写这个系列是用的是目前最新版本4.0.10,虚拟 ...
- Redis系列(七)Redis面试题
Redis 系列: Redis系列(一)Redis入门 Redis系列(二)Redis的8种数据类型 Redis系列(三)Redis的事务和Spring Boot整合 Redis系列(四)Redis配 ...
- Redis系列(1)之安装
Redis系列(1)之安装 由于项目的需要,最近需要研究下Redis.Redis是个很轻量级的NoSql内存数据库,它有多轻量级的呢,用C写的,源码只有3万行,空的数据库只占1M内存.它的功能很丰富, ...
- Python操作redis系列之 列表(list) (四)
# -*- coding: utf- -*- import redis r =redis.Redis(host=,password="ZBHRwlb1608") 1. Lpush ...
随机推荐
- python 常用对linux系统文件及目录的操作
目录 1.取得当前目录——os.getcwd() >>> import os >>> s=os.getcwd()#获得当前运行脚本所在目录 >>> ...
- [整理]内存重叠之memcpy、memmove
函数原型: void *memcpy( void *dest, const void *src, size_t count ); void *memmove( void* dest, const vo ...
- 知识笔记:jQuery 事件对象属性小结
使用事件自然少不了事件对象.因为不同浏览器之间事件对象的获取,以及事件对象的属性都有差异,导致我们很难跨浏览器使用事件对象.jQuery中统一了事件对象,当绑定事件处理函数时,会将jQuery格式化后 ...
- 【转】线程间操作无效: 从不是创建控件“textBox2” 的线程访问它。
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...
- HDU 1019 Least Common Multiple GCD
解题报告:求多个数的最小公倍数,其实还是一样,只需要一个一个求就行了,先将答案初始化为1,然后让这个数依次跟其他的每个数进行求最小公倍数,最后求出来的就是所有的数的最小公倍数.也就是多次GCD. #i ...
- HTTP请求方法 之 HEAD
HTTP请求方法并不是只有GET和POST,只是最常用的.据RFC2616标准(现行的HTTP/1.1)得知,通常有以下8种方法:OPTIONS.GET.HEAD.POST.PUT.DELETE.TR ...
- 诺贝斯特(厦门)电气有限公司http://www.thebest.cn.com/
诺贝斯特(厦门)电气有限公司,公司位于厦门市湖里区塘边社168号.是一家专注于智能电网用户端智能配用电以及电气安全产品研发.生产和销售的高新技术企业:致力于为工矿企业.建筑楼宇以及基础设施等智能电网用 ...
- Material Design In Action——重构bilibili客户端
前言 哔哩哔哩动画是中国大陆的一家弹幕视频网站,在中国二次元用户中颇受欢迎. 哔哩哔哩动画之前推出过采用 Android Design 的 Android 客户端,虽然有使用了部分过时控件(例如 Sc ...
- SolrJ API 官方文档最佳实践
以下内容译自Solr Wiki官方文档,版权没有,随意转载. Solrj 是一个访问solr的Java客户端.它提供了一个java接口用于添加更新和查询solr索引.本页面介绍SolrJ最新版本1.4 ...
- C#事件实现文件下载时进度提醒
C#中的事件是建立在委托的基础上,标准的事件模型应该包括以下几点: 声明一个用于定义事件的委托,这里用系统自带的泛型委托原型EventHandler<TEventArgs>,如:publi ...