命令 | 格式 | 做用 | 返回结果 |
---|---|---|---|
WATCH | WATCH key [key ...] | 将给出的Keys 标记为监测态 ,做为事务执行的条件 |
always OK. |
UNWATCH | UNWATCH | 清除事务中Keys 的 监测态 ,若是调用了EXEC or DISCARD,则没有必要再手动调用UNWATCH |
always OK. |
MULTI | MULTI | 显式 开启redis事务 ,后续commands 将排队,等候使用EXEC进行原子执行 |
always OK. |
EXEC | EXEC | 执行事务中的commands 队列,恢复链接状态。若是WATCH在以前被调用,只有监测 中的Keys 没有被修改,命令才会被执行,不然中止执行(详见下文,CAS机制 ) |
成功: 返回数组 —— 每一个元素对应着原子事务中一个 command 的返回结果;失败: 返回 NULL (Ruby 返回`nil` ); |
DISCARD | DISCARD | 清除事务中的commands 队列,恢复链接状态。若是WATCH在以前被调用,释放 监测 中的Keys |
always OK. |
注意:程序员
------
MULTI
,EXEC
,DISCARD
才是显式
开启并控制事务的经常使用命令,可类比关系型数据库
中的BEGAIN
,COMMIT
,ROLLBACK
(事实上,差距很大);redis
------
WATCH
命令的使用是为了解决事务并发
产生的不可重复读
和幻读
的问题(简单理解为给Key加锁
);数据库
MULTI, EXEC, DISCARD and WATCH 是Redis事务的基础。用来显式开启并控制一个事务,它们容许在一个步骤中执行一组命令
。并提供两个重要的保证:编程
命令队列
做为一个单独的原子操做被执行。commands
;commands
都被执行。同时,redis使用AOF(append-only file),使用一个额外的write操做
将事务写入磁盘。若是发生宕机,进程奔溃等状况,可使用redis-check-aof tool 修复append-only file,使服务正常启动,并恢复部分操做。数组
使用MULTI
命令显式开启
Redis事务。 该命令老是以OK回应。此时用户能够发出多个命令,Redis不会执行这些命令,而是将它们排队
。EXEC
被调用后,全部的命令都会被执行。而调用DISCARD
能够清除
事务中的commands队列
并退出事务
。bash
>MULTI
OK
>INCR foo
QUEUED
>INCR bar
QUEUED
>EXEC
1)(整数)1
2)(整数)1
复制代码
从上面的命令执行中能够看出,EXEC
返回一个数组
,其中每一个元素都是事务中单个命令的返回结果,并且顺序与命令的发出顺序相同
。 当Redis链接处于MULTI
请求的上下文中时,全部命令将以字符串QUEUED
(从Redis协议的角度做为状态回复发送)做为回复,并在命令队列
中排队。只有EXEC被调用时,排队的命令才会被执行,此时才会有真正的返回结果
。服务器
事务期间,可能会遇到两种命令错误:并发
EXEC
命令以前出现错误(COMMAND
排队失败)。语法错误
(参数数量错误,错误的命令名称...);某些关键条件
,如内存不足的状况(若是服务器使用maxmemory
指令作了内存限制
)。客户端会在EXEC
调用以前检测第一种错误。 经过检查排队命令的状态回复
(***注意:这里是指排队
的状态回复
,而不是执行结果
***),若是命令使用QUEUED
进行响应,则它已正确排队,不然Redis将返回错误。若是排队命令时发生错误,大多数客户端将停止该事务并清除命令队列
。然而:app
Redis 2.6.5以前
,这种状况下,在EXEC
命令调用后,客户端会执行命令的子集(成功排队的命令)而忽略以前的错误。Redis 2.6.5开始
,服务端会记住在累积命令期间发生的错误,当EXEC
命令调用时,将拒绝执行事务,并返回这些错误,同时自动清除命令队列
。>MULTI
+OK
>INCR a b c
-ERR wrong number of arguments for 'incr' command
复制代码
这是因为
INCR
命令的语法错误,将在调用EXEC
以前被检测出来,并终止事务(version2.6.5+)。ui
EXEC
命令以后出现错误。错误的值
对某个key
执行操做(如针对String
值调用List
操做)EXEC
命令执行以后发生的错误并不会被特殊对待:即便事务中的某些命令执行失败,其余命令仍会被正常执行
。
>MULTI
+OK
>SET a 3
+QUEUED
>LPOP a
+QUEUED
>EXEC
*2
+OK
-ERR Operation against a key holding the wrong kind of value
复制代码
EXEC
返回一个包含两个元素的字符串数组,一个元素是OK
,另外一个是-ERR……
。- 可否将错误合理的反馈给用户这取决于
客户端library
(如:Spring-data-redis.redisTemplate
)的自身实现。- 须要注意的是,即便命令失败,队列中的全部其余命令也会被处理----Redis不会中止命令的处理。
重点
)事实上Redis命令
在事务执行时可能会失败,但仍会继续执行剩余命令
而不是Rollback
(事务回滚)。若是你使用过关系数据库
,这种状况可能会让你感到很奇怪。然而针对这种状况具有很好的解释:
Redis命令
可能会执行失败,仅仅是因为错误的语法被调用(命令排队时检测不出来的错误),或者使用错误的数据类型操做某个Key
: 这意味着,实际上失败的命令都是编程错误形成的,都是开发中可以被检测出来的,生产环境中不该该存在。(这番话,完全甩锅,“都是大家本身编程错误,与咱们无关”。)Rollback
,Redis
内部简洁而且更加高效。“若是错误就是发生了呢?”这是一个反对Redis
观点的争论
。然而应该指出的是,一般状况下,回滚并不能挽救编程错误。鉴于没有人可以挽救程序员的错误,而且Redis命令
失败所需的错误类型不太可能进入生产环境,因此咱们选择了不支持错误回滚(Rollback)这种更简单快捷的方法。
DISCARD
被用来停止事务。事务中的全部命令将不会被执行,链接将恢复正常状态。
> SET foo 1
OK
> MULTI
OK
> INCR foo
QUEUED
> DISCARD
OK
> GET foo
"1"
复制代码