Redis-事务即简单锁应用
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-事务即简单锁应用的更多相关文章
- Redis事务和分布式锁
Redis事务 Redis中的事务(transaction)是一组命令的集合.事务同命令一样都是Redis最小的执行单位,一个事务中的命令要么都执行,要么都不执行.Redis事务的实现需要用到 MUL ...
- Redis事务的简单理解
Redis事务的命令如下所示: 先以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令 示例如下: //开始一个事务 > MU ...
- redis事务和乐观锁
1 MULTI/EXEC 执行本事务. MULTI set foo bar get foo set foo hello EXEC 在EXEC执行前,三条命令都放入队列中,然后EXEC触发执行.没有回滚 ...
- redis的事务(简单介绍)
1.简单描述 redis对事务的支持目前还是比较简单.redis只能保证一个client发起的事务中的命令是可以连续的执行,而中间不会插入其他client的命令.由于redis是但现场来处理所有cli ...
- Redis事务及锁应用
Redis只支持简单的事务,不像mysql那样比较完整严格,对数据的完整性也维持的很好.redis的开启事务实际上只是将开启事务之后的一段命令用队列包裹起来了,当调用redis的执行命令(exec)全 ...
- java架构之路-(Redis专题)简单聊聊redis分布式锁
这次我们来简单说说分布式锁,我记得过去我也过一篇JMM的内存一致性算法,就是说拿到锁的可以继续操作,没拿到的自旋等待. 思路与场景 我们在Zookeeper中提到过分布式锁,这里我们先用redis实现 ...
- redis 事务 & 锁
参考:https://www.cnblogs.com/DeepInThought/p/10720132.html Redis不保证原子性:Redis中,单条命令是原子性执行的,但事务不保证原子性,且没 ...
- redis事务机制和分布式锁
Redis事务机制 严格意义来讲,Redis的事务和我们理解的传统数据库(如mysql)的事务是不一样的:Redis的事务实质上是命令的集合,在一个事务中要么所有命令都被执行,要么所有事物都不执行. ...
- Redis的“假事务”与分布式锁
关注公众号:CoderBuff,回复"redis"获取<Redis5.x入门教程>完整版PDF. <Redis5.x入门教程>目录 第一章 · 准备工作 第 ...
- 跟我一起学Redis之Redis事务简单了解一下
前言 关系数据库中的事务,小伙伴们应该是不陌生了,不管是在开发还是在面试过程中,总有两个问题逃不掉: 说说事务的特性: 事务隔离级别是怎么一回事? 事务处理不好,数据就可能不准确,最终就会导致业务出问 ...
随机推荐
- 可选参数、命名参数、.NET的特殊类型、特性
1.可选参数和命名参数 1.1可选参数 语法: [修饰符] 返回类型 方法名(必选参数n,可选参数n) 注意: 1.必选参 ...
- jQuery淡入淡出的轮播图
html结构: <div class="banna"> <ul class="img"> ...
- Spring的JDBC(非web程序)的简单例子
第一步: spring配置applicationContext.xml文件,放在src下面: <?xml version="1.0" encoding="UTF-8 ...
- Kafka 源代码分析之FileMessageSet
这里主要分析FileMessageSet类 这个类主要是管理log消息的内存对象和文件对象的类.源代码文件在log目录下.这个类被LogSegment类代理调用用来管理分片. 下面是完整代码.代码比较 ...
- 【Android Developers Training】 13. 支持不同平台版本
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 『转』MarsEdit快速插入源代码
开始用MarsEdit来写博文,客户端的,毕竟是要方便的多啊. 遇到的第一个问题就是:MarsEdit没有提供快速插入源代码的工具,而对于我这枚码农而言,这个就有点太杯具了. 简单研究了一下,发现Ma ...
- JavaWeb 后端 <十二> 之 过滤器 filter 乱码、不缓存、脏话、标记、自动登录、全站压缩过滤器
一.过滤器是什么?有什么? 1.过滤器属于Servlet规范,从2.3版本就开始有了. 2.过滤器就是对访问的内容进行筛选(拦截).利用过滤器对请求和响应进行过滤
- UVa455 Periodic String 的wronganswer问题探讨,以及AC的新思路
题目的意思是一个字符串有某个长度为k的字符串通过不断重复形成的,而k被称为该字符串的周期.而我们所要做的是找出该字符串的最小周期. input The first line is an integer ...
- Java数据类型+练习
java基础数据类型: 四类八种: 1, 整数型 byte 2的8次方(取值范围--<-128~127>)--1个字节 short 2的16次方--2个 int 2的32次方- ...
- vim的tab键设定
多在windows上编程的童鞋可能习惯于感受tab键为4个空格的长度,不过在linux系统中一般默认设定tab键为8个空格长度来显示.事实上tab也确实是8个空格的长度.不过由于习惯问题,某些童鞋还是 ...