1. Redis事务是什么
- 一次执行多个命令,本质是一组命令的集合。事务中的所有命令都会序列化,按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断
2. 事务相关的命令
-
watch key [key...]
:监视一个或多个key。如果在事务执行之前这个或这些key被其他命令锁改动,那么事务会被打断 -
multi
:标记一个事务块的开始 -
exec
:执行所有事务块内的命令 -
discard
:取消事务,放弃执行事务块内的所有命令 -
unwatch
:取消watch命令对所有key的监视
3. 事务案例演示
-
正常执行
multi # 开启事务 set k1 v1 # 入队 set k2 v2 # 入队 get k2 # 入队 set k3 v3 # 入队 .... # 入队 exec # 执行事务
-
放弃事务
multi # 开启事务 set k1 v1 # 入队 set k2 v2 # 入队 get k2 # 入队 set k3 v3 # 入队 .... # 入队 discard # 放弃事务
-
命令语句错误(全体连坐)
multi set k1 v1 set k2 v2 get k2 get set excprisks # 这里会入队错误 set k5 v5 ... exec
此时
get set excprisks
加入队列报错,导致当前事务中全部语句不能被执行 -
执行时出错(冤头债主)
multi set k1 v1 incr k1 # 此时v1为非数字,执行时会出错 set k2 v2 get k2 ... exec
此时
incr k1
加入队列成功,只是执行的时候会报错。但是其他命令都会成功执行
由第3、4点得出:Redis的事务是部分支持
4. watch监控
-
注意:一定是先监控,再开启事务
-
案例
-
说明:此时Redis库中已有值balance-100、debt-0
-
watch balance # 此时balance为100,debt为0 # 假设,这里有其他客户端A将balance修改为200 multi decrby balance 20 incrby debt 20 exec
本次事务执行失败。因为在事务执行之前balance数据已经不是watch时的值。此时,获取到的balance为200。
如果watch后,数据被人改了,执行unwatch命令,取消对所有key的watch。然后再重新watch,再执行事务。
-
-
总结
watch 类似乐观锁,事务提交时,如果key的值被其他客户端修改了,整个事务队列不会执行。
通过watch命令在事务之前监控了多个keys,如若在watch之后有任何被监视的key的值发生了变化,exec命令执行的事务都会被放弃,并返回Nullmulti-bulk告诉调用这事务执行失败。
5. Redis事务总结
- 单独的隔离操作
事务中所有命令都会序列化,按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。 - 没有隔离级别的概念
队列中的命令没有提交之前都不会实际的被执行,也就不存在事务内的查询要看到事务里的更新。 - 不保证原子性
redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚。