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事务简单了解一下
前言 关系数据库中的事务,小伙伴们应该是不陌生了,不管是在开发还是在面试过程中,总有两个问题逃不掉: 说说事务的特性: 事务隔离级别是怎么一回事? 事务处理不好,数据就可能不准确,最终就会导致业务出问 ...
随机推荐
- Cordova各个插件使用介绍系列(四)—canvas2ImagePlugin保存二维码到手机本地
详情链接地址:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/cordova-4-canvas2imageplugin/ 在前面几篇 ...
- 一篇文章带你快速入门createjs
开始用createjs这个框架的时候,发现网上的相关教程还是挺少的,所以写一篇文章,方便日后查看. createjs简介 官网:http://www.createjs.cc/ createjs中包 ...
- net core 程序docker打包镜像并发布到官方store
学习一个技术的第一步,总是要先打印或显示一个hello world的.当然,学习docker也不例外.上一篇文章已经简单的介绍了环境的安装和配置.接下来就要打印我们的hello world了. 首先我 ...
- MongoDB 3.4版本, C# 驱动 2.4 操作
private static string _connStr = "mongodb://127.0.0.1:27017"; private static string _dbNam ...
- mysql的my.ini文件详解
mysql数据库在配置时包含很多信息:端口号,字符编码,指定根路径 basedir,指定数据存放的路径等信息 mysql的字体编码分为两种: 服务器编码 客户端输入的编码 通常服务器的编码都是utf- ...
- MVP架构
一.介绍 MVP(Model View Presenter)架构是从著名的MVC(Model View Controller)架构演变而来的.对于在Android应用中开发就可以视为是MVC架构,布局 ...
- js原生获取className&多选一
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 4.jsp的内置对象
1.jsp有九大内置对象 out request response session application page pagecontext exception config 2.用户发请求 requ ...
- 分页插件Jpages的使用
项目原因需要前端做分页表格,之前做了一个ul的分页效果,但是感觉自己写还是造轮子了,今天网上看到Jpqges插件就试了下,感觉平时使用挺方便的,写一下自己的使用过程. 先上套图,下载下来就2个js和1 ...
- 探索Windows命令行系列(7):通过命令编译C#类和Java类
1.编译 C# 类 1.1.C# 编译工具 1.2.编译一个 C# 类 1.3.编译多个 C# 类 2.编译 Java 类 2.1.Java 编译工具 2.2.编译 Java 类 3.组合命令符 4. ...