Redis 事务 transaction https://redis.io/topics/transactions#cas
相关命令
- 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 来通知事务失败了.
来源: http://www.jianshu.com/p/76dd2a0b2224