Redis支持简单的事务, Redis允许一组命令在单一步骤中执行, 事务有两个属性

  • 事务是一个单独的隔离操作, 事务中所有的命令都会序列化, 按照顺序执行.
  • Redis事务是原子性的, 即要么都执行, 要么都不执行

一个事务从开始到执行会经历三个阶段

  • 开始事务
  • 命令入队
  • 执行事务

redis 与 mysql 事务的对比:

mysql redis
开启 start transaction multi
语句 普通的sql 普通命令
失败 rollback回滚 discard取消
成功 commit exec

__注__: rollback 与 discard 的区别
如果已经成功执行了2条语句, 第3条语句出错
rollback后, 前两条语句影响消失
discard只是结束本次事务, 前两条语句造成的影响依然存在
__注__:
在multi后面的语句中, 语句出错可能有2种情况
1. 语法本身有问题, 这种错误exec时报错, 所有语句得不到执行
2. 语法本身没错误, 但适用对象有问题, 比如zadd操作list对象, exec后会执行正确的语句, 并跳过有不适当的语句


使用redis模拟银行转账操作:

  • 正常情况
127.0.0.1:6379> set wang 200    #wang有200
OK
127.0.0.1:6379> set zhao 700 #zhao有700
OK
127.0.0.1:6379>
127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379> decrby zhao 100 #zhao减100
QUEUED
127.0.0.1:6379> incrby wang 100 #wang加100
QUEUED
#以上两个QUEUED表示两条语句被放在队列里面, exec前并没有执行
127.0.0.1:6379> exec #执行完毕
1) (integer) 600
2) (integer) 300
127.0.0.1:6379>
  • 意外情况
127.0.0.1:6379> multi    开启事务
OK
127.0.0.1:6379>
127.0.0.1:6379> decrby zhao 100 #zhao减100
QUEUED
127.0.0.1:6379> das #输入一个错误的命令
(error) ERR unknown command 'das'
127.0.0.1:6379> exec #执行, 提示被忽略
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379>
127.0.0.1:6379> mget zhao wang #zhao 和 wang的值不变
1) "600"
2) "300"
127.0.0.1:6379>
  • 另一种报错情况
127.0.0.1:6379> multi
OK
127.0.0.1:6379>
127.0.0.1:6379> decrby zhao 100 #zhao减100
QUEUED
127.0.0.1:6379> sadd wang pig #故意把wang当做数组加入一个key, 发现并没有报错,
#因为这条语句被存放在队列里, 并没有被执行
QUEUED
127.0.0.1:6379> exec #此时语句才被执行, 所以报错, 但是zhao依然减了100, 说明执行了正确的语句, 跳过了不正取的语句, 影响还在
1) (integer) 500
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379>
127.0.0.1:6379> mget zhao wang
1) "500"
2) "300"
127.0.0.1:6379>
  • discard取消
127.0.0.1:6379> mget wang zhao
1) "400"
2) "400"
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby zhao 100
QUEUED
127.0.0.1:6379> incrby wang 100
QUEUED
127.0.0.1:6379>
127.0.0.1:6379> discard #取消后值没变
OK
127.0.0.1:6379>
127.0.0.1:6379> mget wang zhao
1) "400"
2) "400"
127.0.0.1:6379> exec
(error) ERR EXEC without MULTI
127.0.0.1:6379>
127.0.0.1:6379> mget zhao wang
1) "400"
2) "400"
127.0.0.1:6379>
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby zhao 100
QUEUED
127.0.0.1:6379> sadd wang pig
QUEUED
127.0.0.1:6379>
127.0.0.1:6379> exec
1) (integer) 300
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379>
127.0.0.1:6379> discard #不能discard
(error) ERR DISCARD without MULTI
127.0.0.1:6379>
127.0.0.1:6379> mget zhao wang
1) "300"
2) "400"
127.0.0.1:6379>

watch key1 key2 ... keyN

作用: 监听 key1 key2 keyN有没有变化, 如果有变化, 则事务取消

unwatch(不加key): 取消所有 watch 监听

场景: 一个人正在买票, ticket-1, money-100, 而票只有一张, 如果在我multi之后, exec之前票被别人买走, 即ticket变为0了, 怎么办?

127.0.0.1:6379> set ticket 1    #加入只有1张票
OK
127.0.0.1:6379> set lisi 300 #lisi有300
OK
127.0.0.1:6379> set wang 300 #wang有300
OK
127.0.0.1:6379>
127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379> decr ticket #票数-1
QUEUED
127.0.0.1:6379> decrby lisi 100 #lisi准备买-100
QUEUED
127.0.0.1:6379> #此处还没有exec

假如就在exec前票被别人买走, 打开另一个终端

127.0.0.1:6379> decr ticket    #票-1
(integer) 0
127.0.0.1:6379> get ticket #此时票数为0
"0"
127.0.0.1:6379>

此时提交lisi

127.0.0.1:6379> exec
1) (integer) -1 #票变为-1
2) (integer) 200 #钱-100
127.0.0.1:6379>

因此上面的过程不合理


要解决上面的情况,要采用监视

127.0.0.1:6379> set ticket 1    #票数为1
OK
127.0.0.1:6379> set lisi 200 #lisi钱是100
OK
127.0.0.1:6379> set wang 300 #wang是300
OK
127.0.0.1:6379>
127.0.0.1:6379> watch ticket #监控ticket有没有变动, 有变动的话则事务取消
OK
127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379> decr ticket #ticket-1
QUEUED
127.0.0.1:6379> decrby lisi 100 #钱-100
QUEUED
127.0.0.1:6379>

在exec前票又被另一个人买走了

127.0.0.1:6379> decr ticket
(integer) 0
127.0.0.1:6379> get ticket
"0"
127.0.0.1:6379>

此时票数为0, lisi提交

127.0.0.1:6379>
127.0.0.1:6379> exec #失败
(nil)
127.0.0.1:6379>
127.0.0.1:6379> get lisi #钱并没有减少
"200"
127.0.0.1:6379>

Redis-事务即简单锁应用的更多相关文章

  1. Redis事务和分布式锁

    Redis事务 Redis中的事务(transaction)是一组命令的集合.事务同命令一样都是Redis最小的执行单位,一个事务中的命令要么都执行,要么都不执行.Redis事务的实现需要用到 MUL ...

  2. Redis事务的简单理解

    Redis事务的命令如下所示: 先以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令 示例如下: //开始一个事务 > MU ...

  3. redis事务和乐观锁

    1 MULTI/EXEC 执行本事务. MULTI set foo bar get foo set foo hello EXEC 在EXEC执行前,三条命令都放入队列中,然后EXEC触发执行.没有回滚 ...

  4. redis的事务(简单介绍)

    1.简单描述 redis对事务的支持目前还是比较简单.redis只能保证一个client发起的事务中的命令是可以连续的执行,而中间不会插入其他client的命令.由于redis是但现场来处理所有cli ...

  5. Redis事务及锁应用

    Redis只支持简单的事务,不像mysql那样比较完整严格,对数据的完整性也维持的很好.redis的开启事务实际上只是将开启事务之后的一段命令用队列包裹起来了,当调用redis的执行命令(exec)全 ...

  6. java架构之路-(Redis专题)简单聊聊redis分布式锁

    这次我们来简单说说分布式锁,我记得过去我也过一篇JMM的内存一致性算法,就是说拿到锁的可以继续操作,没拿到的自旋等待. 思路与场景 我们在Zookeeper中提到过分布式锁,这里我们先用redis实现 ...

  7. redis 事务 & 锁

    参考:https://www.cnblogs.com/DeepInThought/p/10720132.html Redis不保证原子性:Redis中,单条命令是原子性执行的,但事务不保证原子性,且没 ...

  8. redis事务机制和分布式锁

    Redis事务机制 严格意义来讲,Redis的事务和我们理解的传统数据库(如mysql)的事务是不一样的:Redis的事务实质上是命令的集合,在一个事务中要么所有命令都被执行,要么所有事物都不执行.  ...

  9. Redis的“假事务”与分布式锁

    关注公众号:CoderBuff,回复"redis"获取<Redis5.x入门教程>完整版PDF. <Redis5.x入门教程>目录 第一章 · 准备工作 第 ...

  10. 跟我一起学Redis之Redis事务简单了解一下

    前言 关系数据库中的事务,小伙伴们应该是不陌生了,不管是在开发还是在面试过程中,总有两个问题逃不掉: 说说事务的特性: 事务隔离级别是怎么一回事? 事务处理不好,数据就可能不准确,最终就会导致业务出问 ...

随机推荐

  1. salesforce零基础学习(七十三)ProcessInstanceWorkItem/ProcessInstanceStep/ProcessInstanceHistory浅谈

    对于审批流中,通过apex代码进行审批操作一般都需要获取当前记录对应的ProcessInstanceWorkitem或者ProcessInstanceStep然后执行Approval.process操 ...

  2. final用法

    1.修饰类 如果一个类被定义为final类型,那么该类无法被其他类继承,该类中的所有方法都是final类型的,字段是否是final类型取决于字段自身的定义. 2.修饰方法 一个方法被定义为final类 ...

  3. windbg工具安装配置及dump抓取

    安装与配置windbg 安装与配置windbg的symbol(符号) 第一步 下载WinDBG, 第二步 双击下载的文件安装windbg.安装时注意记住安装到那里了. 第三步 windbg访问符号需要 ...

  4. 基于Dubbo的分布式事务框架(LCN)

    原文地址:http://原文地址:https://github.com/1991wangliang/transaction 基于Dubbo的分布式事务框架(LCN) 该框架依赖Redis/dubbo/ ...

  5. go语言获取变量的数据类型

    package main import "fmt" import "reflect"; var y string = "sdasd" fun ...

  6. Java NIO 核心组件学习笔记

    背景知识 同步.异步.阻塞.非阻塞 首先,这几个概念非常容易搞混淆,但NIO中又有涉及,所以总结一下[1]. 同步:API调用返回时调用者就知道操作的结果如何了(实际读取/写入了多少字节). 异步:相 ...

  7. 【Android Developers Training】 5. 序言:添加Action Bar

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  8. 6.如何使用jedis的线程池

    Basic usage example using Jedis in a multithreaded environment You shouldn't use the same instance f ...

  9. URL和HTTP协议(无图片)

    URL...... 示例: http://localhost/phpwind/searcher.php?keyword=phpwind&type=thread 协议部分:一般是指URL中第一个 ...

  10. 简单总结几种常见web攻击手段及其防御方式

    web攻击手段有几种,本文简单介绍几种常见的攻击手段及其防御方式 XSS(跨站脚本攻击) CSRF(跨站请求伪造) SQL注入 DDOS XSS 概念 全称是跨站脚本攻击(Cross Site Scr ...