1 基本说明
可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其他命令插入,不许加塞。
2 事务相关的几个命令
2.1 MULTI
标记一个事务块的开始
redis> MULTI # 标记事务开始
OK
redis> INCR user_id # 多条命令按顺序入队
QUEUED
redis> INCR user_id
QUEUED
redis> INCR user_id
QUEUED
redis> PING
QUEUED
redis> EXEC # 执行
1) (integer) 1
2) (integer) 2
3) (integer) 3
4) PONG
2.2 EXEC
执行事务内的所有命令
2.3 DISCARD
取消事务,放弃执行事务块内的所有命令
如果正在使用 WATCH
命令监视某个 key,那么取消所有监视,等同于执行命令 UNWATCH
redis> MULTI
OK
redis> PING
QUEUED
redis> SET greeting "hello"
QUEUED
redis> DISCARD
OK
2.4 WATCH
监视一个(或多个) key
如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断(也就是隔离性)。
事务执行完成,WATCH也结束了。
watch指令,类似乐观锁,事务提交时,如果Key的值已经被别的客户端改变,比如某个list已经被别的客户端push/pop过了,整个事务队列都不会被执行
redis> WATCH lock lock_times
OK
2.5 UNCATCH
取消 WATCH 命令对所有 key 的监视
如果在执行 WATCH 命令之后, EXEC 命令或 DISCARD 命令先被执行了的话,那么就不需要再执行 UNWATCH 了。
因为 EXEC 命令会执行事务,因此 WATCH 命令的效果已经产生了,WATCH也就结束了;而 DISCARD 命令在取消事务的同时也会取消所有对 key 的监视,因此这两个命令执行之后,就没有必要执行 UNWATCH 了
3 关于MULTI事务的简要说明
当我们开启一个事务的时候,输入一条条的指令。
情况1:当某条命令格式没有问题,但是执行出错,比如incr k1,k1自增命令,如果k1不是数字,那么这条命令会报错。但是事务中这条命令之外的其他命令照样会执行(这条命令之前和之后的命令都会正常执行)。也就是说,在这种情况下,这些命令的执行并不是原子性执行的。
情况2:当事务中某条命令格式就错误。那么事务中其他命令都不会执行。而在编码的角度来看的话,我们调用相关写方法,不会出现这个问题。
4 示例
1)正常执行
2)放弃事务
3)若在事务队列中存在语法错误,则执行EXEC命令时,所有命令都不会执行
4)若在事务队列中存在语法性错误(类似于java的1/0的运行时异常),则执行EXEC命令时,其他正确命令会被执行,错误命令抛出异常。
5)使用watch
案例一:使用watch检测balance,事务期间balance数据未变动,事务执行成功
案例二:使用watch检测balance,在开启事务后(标注1处),在新窗口执行标注2中的操作,更改balance的值,模拟其他客户端在事务执行期间更改watch监控的数据,然后再执行标注1后命令,执行EXEC后,事务未成功执行。
新窗口
一但执行 EXEC无论事务使用执行成功, WARCH 对变量的监控都将被取消。
故当事务执行失败后,需重新执行WATCH命令对变量进行监控,并开启新的事务进行操作。