redis 事务 主要通过
MULTI, EXEC, DISCARD and WATCH
等命令实现。这些命令协同合作使redis能够一次性执行一组命令。
特性
- 事务过程中的命令按顺序依次执行,执行过程不受其他客户端发出的命令影响,事务中的一组命令是一个与外界隔离的操作单元。
- 命令要么全部执行,要么全不执行。事务中命令的执行由EXEC命令触发。
用法
开启事务 --> MULTI (成功开启后,redis client返回`OK`)
执行事务 --> EXEC
开启后输入的所有命令将进入一个队列,输入EXEC命令后统一执行。若在执行EXEC之前执行DISCARD命令,命令队列将被清空,终止事务。
事务过程中出现错误
(即MULTI 和 EXEC命令之间)
- 某条命令未能入队
- 执行EXEC之后,某条命令执行出错
第①种情况:redis服务器拒绝执行事务中的命令,相关命令不会入队,EXEC时返回异常,并终止事务。
第②种情况:有问题的命令会执行失败,不过所有其它命令都将正常执行。
Redis为什么没有回滚机制
- EXEC之前,积累命令的时候,redis在检测到的错误后会中止事务
- EXEC之后出现的错误多是由编码错误引起的,这种错误在开发过程中能够发现并消除
- 简化Redis内部设计,提高执行速度
- 回滚机制作用有限,并不能弥补编码错误
DISCARD命令
用于中止正在进行的事务。
使用check-and-set实现的乐观锁
通过WATCH命令在Redis中实现check-and-set(CAS)事务模式。
WATCH命令用于监测键的变化,在事务进行过程中若至少一个键的值发生改变,整个事务将会中止,接着EXEC将返回null,表示事务失败。
WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC
若在WATCH和EXEC之间,其他客户端修改了mykey的值,事务将失败。
We just have to repeat the operation hoping this time we'll not get a new race. This form of locking is called optimistic locking and is a very powerful form of locking. In many use cases, multiple clients will be accessing different keys, so collisions are unlikely – usually there's no need to repeat the operation.
我们需要不断重复WATCH 和 EXEC之间的操作,期望这一次不会出现竞争状态。这种锁机制功能强大,被称为乐观锁。在多种使用场景中,多个客户端在同一时刻会访问不同的键,因此不太可能发生竞争的情况——即,WATCH和EXEC之间的操作通常一次就能完成,不需要自旋。
WATCH命令可接收多个参数,并且可多次调用
执行EXEC之后,所有键将变成UNWATCHed,无论事务中止与否。客户端连接断开之后同理。
不带参数执行UNWATCH命令,会将所有键变为UNWATCHed状态。
欢迎到作者github主页交流