一、是什么
可以一次执行多个命令, 本质是一组命令的集合,一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其他命令插入,不许加塞
二、能干啥
一个队列中,一次性,顺序性的执行一系列命令
三、示例演示
-
正常执行
127.0.0.1:6379> MULTI // 开启事务 OK 127.0.0.1:6379> set k1 v1 //入队 QUEUED 127.0.0.1:6379> set k2 v2 QUEUED 127.0.0.1:6379> get k2 QUEUED 127.0.0.1:6379> set k3 v3 QUEUED 127.0.0.1:6379> EXEC //执行事务 1) OK // 执行结果 2) OK 3) "v2" 4) OK
-
放弃事务
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> set k1 v1 QUEUED 127.0.0.1:6379> set k2 22 QUEUED 127.0.0.1:6379> set k3 33 QUEUED 127.0.0.1:6379> DISCARD //放弃事务 OK 127.0.0.1:6379> get k2 // 获取到的还是先前设置的v2 "v2"
-
一损俱损
127.0.0.1:6379> MULTI OK 127.0.0.1:6379> set k4 v4 QUEUED 127.0.0.1:6379> setget k5 55 //命令错误,全都执行不成功 (error) ERR unknown command 'setget' 127.0.0.1:6379> set k6 v6 QUEUED 127.0.0.1:6379> EXEC (error) EXECABORT Transaction discarded because of previous errors. 127.0.0.1:6379> get k4 // 获取的为nil (nil)
-
冤头债主
127.0.0.1:6379> get k1 "v1" 127.0.0.1:6379> MULTI OK 127.0.0.1:6379> INCR k1 //执行没有报错,运行的时候报错,不影响其他的 QUEUED 127.0.0.1:6379> set k4 v4 QUEUED 127.0.0.1:6379> set k5 v5 QUEUED 127.0.0.1:6379> get k4 QUEUED 127.0.0.1:6379> EXEC 1) (error) ERR value is not an integer or out of range 2) OK 3) OK 4) "v4" // 可以获取到值
四、watch监控
watch命令监视一个(或多个)key,如果在事务执行之前这个(或这些)key 被其他命令所改动,那么事务将被打断
unwatch 取消watch命令对所有key的监视
-
悲观锁/乐观锁/CAS(Check And Set)
悲观锁
,就是很悲观,每次拿数据都认为别人会修改,多以拿数据前会上锁,这样别人拿数据就会阻塞,直到它拿到锁,传统关系型数据库里用到了很多这种锁机制,如行锁,表锁等,读锁,血锁,都是在操作之前上锁乐观锁
,就是很乐观,每次拿数据都认为别人不会修改,所以不上锁,但更新时会判断一下在此期间有没有人更新过这个数据,可以使用版本号等机制,这样可以提高吞吐量。乐观锁策略:提交版本必须大于记录当前版本才能执行更新
无加塞篡改:
127.0.0.1:6379> set balance 100 //信用卡余额100 OK 127.0.0.1:6379> set debt 0 //信用卡债务20 OK 127.0.0.1:6379> watch balance // 监控余额 OK 127.0.0.1:6379> MULTI OK 127.0.0.1:6379> DECRBY balance 20 QUEUED 127.0.0.1:6379> INCRBY debt 20 QUEUED 127.0.0.1:6379> EXEC 1) (integer) 80 //余额减少20 2) (integer) 20
无加塞篡改:
127.0.0.1:6379> set balance 100 //信用卡余额100 OK 127.0.0.1:6379> set debt 0 //信用卡债务20 OK 127.0.0.1:6379> watch balance // 监控余额 OK 127.0.0.1:6379> MULTI OK 127.0.0.1:6379> DECRBY balance 20 QUEUED 127.0.0.1:6379> INCRBY debt 20 QUEUED 127.0.0.1:6379> EXEC 1) (integer) 80 //余额减少20 2) (integer) 20
有加塞篡改:
开启两个会话窗口
第一个会话窗口watch指令执行完,设置余额为800,最后提交失败,余额变为800
五、小结
watch指令,类似乐观锁,事务提交时,如果key的值已被别的客户端改变,整个事务都不会被执行
通过watch命令在事务执行前监控了多个keys,倘若在watch之后有任何key的值发生变化,exec命令执行的事务都将被放弃
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。