Redis事务
redis事务就是一个命令执行的队列,将一系列预定义的命令包装成一个整体,在执行时,就按这个顺序依次执行,中间不会被打断或干扰
事务的基本操作
- 开启事务
multi
作用: 设定事务的开启位置,从这句命令之后,后续所有的指令都会被加入事务队列,并不会立刻执行。
- 执行事务
exec
作用: 设定事务的结束位置,同时执行事务,返回事务队列里每条指令的执行结果。
- 撤销事务
discard
作用:终止当前事务的定义,前面添加的语句全部作废
特殊情况
- 定义事务的过程中,命令格式输入错误怎么办?
- 如果是语法错误,那整体事务中的所有命令都不会执行,包括正确的指令
- 定义事务的过程中,命令执行错误怎么办?
- 如果指令格式正确,但执行出现错误,如list的命令被错误的用在了一个string的key上,这时只会执行那些正确的,能执行的命令,错误命令不会执行
- 已经执行完的数据会被真实反映在内存上,不会自动回滚,需要程序员在代码中捕捉异常后手动回滚。
WATCH
watch 用来对一个或多个key添加监视,一旦被监视的key被修改或删除,那么未执行(exec
)的事务就会作废,使用此命令,可以实现乐观锁。
watch key1[ key2 ...]
例:
127.0.0.1:8100> set junebao:name zhangsan
OK
# 监视 junebao:name
127.0.0.1:8100> watch junebao:name
OK
# 开启事务
127.0.0.1:8100> multi
OK
127.0.0.1:8100> set junebao:age 21
然后换一个shell,修改被监视的junebao:name
127.0.0.1:8100> set junebao:name lisi
OK
回到第一个窗口,使用exec
来执行事务
# 由于被监视的对象改变,事务未执行成功
127.0.0.1:8100> exec
(nil)
127.0.0.1:8100> get junebao:age
"22"
- 使用
UNWATCH
取消对所有key的监视(不能单个取消)
使用场景
这条命令可以当作一个简单的乐观锁,比如可以使用watch简单实现Redis中提供的INCR
,该操作用来让指定key对应的值自增特定数量,不过重要的是它是一个原子操作。
WATCH myvalue
var = GET myvalue
var = var + 1
multi
SET myvalue var
exec
这样因为监视了myvalue
,所以如果在执行事务的过程中有别的客户端修改了myvalue的值,这里的事务就会被取消,来保证数据一致性。
总结
- 不要混淆Redis单进程和事务,单进程只能保证一条指令不会被打断,但事务是为了保证能让一批指令一起按顺序执行。
- 事务相关指令
指令 | 作用 |
multi | 开启事务 |
exec | 执行事务队列中的指令,返回执行结果 |
watch | 监视单个或多个key,若被监视的key被修改,则未完成的事务全部取消 |
unwatch | 取消对所有key的监视 |