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系列之事务的更多相关文章

  1. Redis系列之key操作命令与Redis中的事务详解(六)

    序言 本篇主要目的有二: 1.展示所有数据类型中key的所有操作命令,以供大家学习,查阅,更深入的挖掘redis潜力. 2.掌握redis中的事务,让你的数据完整性一致性拥有更优的保障. redis命 ...

  2. Redis系列二之事务及消息通知

    一.事务 Redis中的事务是一组命令的集合.一个事务中的命令要么都执行,要么都不执行. 1.事务简介 事务的原理是先将一个事务的命令发送给Redis,然后再让Redis依次执行这些命令.下面看一个示 ...

  3. 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存

    原文:http://blog.csdn.net/heyewu4107/article/details/71009712 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问 ...

  4. Redis系列(三):Redis集群的水平扩展与伸缩

    一.Redis集群的水平扩展 Redis3.0版本以后,有了集群的功能,提供了比之前版本的哨兵模式更高的性能与可用性,但是集群的水平扩展却比较麻烦,接下来介绍下Redis高可用集群如何做水平扩展,在原 ...

  5. Redis系列(三):Redis的持久化机制(RDB、AOF)

    本篇博客是Redis系列的第3篇,主要讲解下Redis的2种持久化机制:RDB和AOF. 本系列的前2篇可以点击以下链接查看: Redis系列(一):Redis简介及环境安装. Redis系列(二): ...

  6. redis系列:redis介绍与安装

    前言 这个redis系列的文章将会记录博主学习redis的过程.基本上现在的互联网公司都会用到redis,所以学习这门技术于你于我都是有帮助的. 博主在写这个系列是用的是目前最新版本4.0.10,虚拟 ...

  7. Redis系列(七)Redis面试题

    Redis 系列: Redis系列(一)Redis入门 Redis系列(二)Redis的8种数据类型 Redis系列(三)Redis的事务和Spring Boot整合 Redis系列(四)Redis配 ...

  8. Redis系列(1)之安装

    Redis系列(1)之安装 由于项目的需要,最近需要研究下Redis.Redis是个很轻量级的NoSql内存数据库,它有多轻量级的呢,用C写的,源码只有3万行,空的数据库只占1M内存.它的功能很丰富, ...

  9. Python操作redis系列之 列表(list) (四)

    # -*- coding: utf- -*- import redis r =redis.Redis(host=,password="ZBHRwlb1608") 1. Lpush ...

随机推荐

  1. Swift控制手电筒操作(iOS)

    手电筒是iphone的一个常用功能,最常用的操作就是turn on和turn off,下面我们来实现一个简单的手电筒操作程序:一个按钮来控制iphone手电筒的On和Off,并且按钮的text也做相应 ...

  2. HDU 1160 FatMouse's Speed (最长上升子序列)

    题目链接 题意:n个老鼠有各自的重量和速度,要求输出最长的重量依次严格递增,速度依次严格递减的序列,n最多1000,重量速度1-10000. 题解:按照重量递增排序,找出最长的速度下降子序列,记录序列 ...

  3. 训练赛第三场A题 zoj 559

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2559 解题报告:比赛的时候的想法是可以确定至少有两对相切的圆,所 ...

  4. CF448C Painting Fence

    传送门 Descriptionzed 最近总是受到 Farmer 的困扰,因此他在自家的门前插了一排栅栏以防农气的入侵.栅栏由 N 个竖条栅栏横向组成,每个竖条栅栏宽度为 1.过了一段时间,zed 觉 ...

  5. [转]closed-form solution (闭合解/解析解)和数值解的理解

    参考整理自:http://hi.baidu.com/cjb366/item/7290773b2d2eb9f2a9842873 closed-form solution :一般翻译为闭合解/解析解.这一 ...

  6. C++ 之Boost 实用工具类及简单使用

    本文将介绍几个 Boost 实用工具类,包括 tuple.static_assert.pool.random 和 program_options等等.需要对标准 STL 具备一定的了解才能充分理解本文 ...

  7. REX系统2

    REX(Real Time Executive)是一个面向嵌入式应用的,简单高效的,抢先式,多任务实时操作系统,支持基于优先级的任务调度算法(支持优先级反转).它提供了任务控制,任务同步,互斥,定时器 ...

  8. oracle11g字符集问题之一

    select * from T_WORK_EXPERIENCE t where ROLE=N'被雇佣者' 因为ROLE为NVARCHAR2(30),所以要加N.pl/sql developer 中可以 ...

  9. linux快速安装mysql教程

    #安装mysql服务器:yum install mysql-server #设置开机启动chkconfig mysqld on#现在启动服务service mysqld start #设置root初始 ...

  10. Codeforces Round #408 (Div. 2)C. Bank Hacking(STL)

    题目链接:http://codeforces.com/problemset/problem/796/C 题目大意:有n家银行,第一次可以攻击任意一家银行(能量低于自身),跟被攻击银行相邻或者间接相邻( ...