redis 事务 transaction
相关命令
DISCARD
EXEC
MULTI
UNWATCH
WATCH
事务
multi
, exec
, discard
, watch
是redis 事务的基础。他们允许在单个步骤执行一组命令。有两个重要的保证。
- 在一个事务的所有命令 都被序列化并且顺序执行。永远不会发生在一个事务的执行的时候另一个client 插入一条请求。这保证了这些命令作为单个隔离的命令。
- 命令要么全部执行,要么全都不执行。所以Redis 事务是原子的。
EXEC
命令触发这个事务的所有命令的执行。
使用
使用multi
命令开始Redis的事务,这个命令总是返回ok。此时用户可以发出多个命令。而不是执行这些命令。redis 会把它放队列里。一旦EXEC
命令被调用,所有命令都会被执行
调用discard
会刷新这个事务 队列,并且退出事务。
> MULTI
OK
> INCR foo
QUEUED
> INCR bar
QUEUED
> EXEC
1) (integer) 1
2) (integer) 1
exec
返回一个返回值的数组。这个数组的每个元素是这个事务的每个命令的响应,按命令相同的顺序执行。
在事务里的错误
在一个事务中可能会出现以下这两种错误
- 一种是在
exec
命令调用之前,例如: 语法错误,内存不够 - 在调用
exec
命令之后,例如: 针对字符串值调用列表的操作
在redis 2.6.5 之后,服务器针对第一种错误会拒绝执行事务,并返回一个错误。自动丢弃这个事务。
在redis2.6.5 之前,会执行正确的那些命令。所以新的行为(2.6.5 之后的行为)能够使他更简单的修复事务。
在exec
命令调用失败之后: 所有其他命令都会被执行,即时有些命令执行失败了。
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set a 3
QUEUED
127.0.0.1:6379> lpop a
QUEUED
127.0.0.1:6379> set a 2
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) OK
127.0.0.1:6379> get a
"2"
redis 事务不支持回滚
为什么不支持回滚?
redis 命令失败的原因只会是语法错误
redis 内部更简单,更快,因为不需要回滚
WATCH
乐观锁
watch
被用来提供check-and-set(CAS) 行为对于redis 事务
例子
client 1
> watch a
> multi
> incr a
client2
> multi
> incr a
> exec
然后client1
> exec
(nil)
当监视的key 在事务期间内被修改了,那exec
命令会返回nil来通知事务失败了。