JavaGuide
JavaGuide copied to clipboard
Redis:WATCH 命令碰到 MULTI 命令时的不同效果
Redis-事务中提到 “WATCH 命令用于监听指定的键,当调用 EXEC 命令执行事务时,如果一个被 WATCH 命令监视的键被修改的话,整个事务都不会执行,直接返回失败”。这个说法似乎不太准确,这里以下面 3 个demo进行说明。
- 同一个session中,watch监视的key在multi之前被修改
根据测试结果可以得知,如果在 MULTI 之前被修改,那么这个事务不会被执行 - 同一个session中,watch监视的key在事务内部被修改
根据测试结果可以得知,如果在 MULTI 之后被修改或者说在事务内部被修改,那么这个事务还是会执行成功 - 同一个session中,watch监视的key在事务内部被修改,但是在事务提交之前被其他 session 修改

可以看出,场景一和场景三其实可以当成同一种情况;另外,WATCH 操作只是 session 级别的,不会影响其他 session,在同一个 session 中,对于同一个 Key ,在事务执行之前最多只能加一个 WATCH,WATCH 监视的 Key 在事务内部被修改后,无论这个事务是否执行成功,这个 Key 上的 WATCH 就会自动取消(有兴趣的同学可以自行验证)可以得出结论:
只有当 WATCH 与 事务 在同一个 session 里,并且被 WATCH 监视的Key,第一次被修改的操作在事务内部,这个事务才会执行成功
,WATCH 操作只是 session 级别的,不会影响其他 session,在同一个 session 中,对于同一个 Key ,在事务执行之前最多只能加一个 WATCH,WATCH 监视的 Key 在事务内部被修改后,无论这个事务是否执行成功,这个 Key 上的 WATCH 就会自动取消(有兴趣的同学可以自行验证)可以得出结论:
感谢补充,受教了👍
Redis-事务中提到 “WATCH 命令用于监听指定的键,当调用
EXEC命令执行事务时,如果一个被WATCH命令监视的键被修改的话,整个事务都不会执行,直接返回失败”。这个说法似乎不太准确,这里以下面 3 个demo进行说明。
- 同一个session中,watch监视的key在multi之前被修改
根据测试结果可以得知,如果在 MULTI 之前被修改,那么这个事务不会被执行
- 同一个session中,watch监视的key在事务内部被修改
根据测试结果可以得知,如果在 MULTI 之后被修改或者说在事务内部被修改,那么这个事务还是会执行成功
- 同一个session中,watch监视的key在事务内部被修改,但是在事务提交之前被其他 session 修改
可以看出,场景一和场景三其实可以当成同一种情况;另外,WATCH 操作只是 session 级别的,不会影响其他 session,在同一个 session 中,对于同一个 Key ,在事务执行之前最多只能加一个 WATCH,WATCH 监视的 Key 在事务内部被修改后,无论这个事务是否执行成功,这个 Key 上的 WATCH 就会自动取消(有兴趣的同学可以自行验证)可以得出结论:
只有当 WATCH 与 事务 在同一个 session 里,并且被 WATCH 监视的Key,第一次被修改的操作在事务内部,这个事务才会执行成功
表述完善如下:
你可以通过WATCH 命令监听指定的 Key,当调用 EXEC 命令执行事务时,如果一个被 WATCH 命令监视的 Key 被 其他客户端/Session 修改的话,整个事务都不会被执行。
# 客户端 1
> SET PROJECT "RustGuide"
OK
> WATCH PROJECT
OK
> MULTI
OK
> SET PROJECT "JavaGuide"
QUEUED
# 客户端 2
# 在客户端 1 执行 EXEC 命令提交事务之前修改 PROJECT 的值
> SET PROJECT "GoGuide"
# 客户端 1
# 修改失败,因为 PROJECT 的值被客户端2修改了
> EXEC
(nil)
> GET PROJECT
"GoGuide"
不过,如果 WATCH 与 事务 在同一个 Session 里,并且被 WATCH 监视的 Key 被修改的操作发生在事务内部,这个事务是可以被执行成功的(相关 issue :WATCH 碰到 MULTI 时的不同效果)。
事务内部修改 WATCH 监视的 Key:
> SET PROJECT "JavaGuide"
OK
> WATCH PROJECT
OK
> MULTI
OK
> SET PROJECT "JavaGuide1"
QUEUED
> SET PROJECT "JavaGuide2"
QUEUED
> SET PROJECT "JavaGuide3"
QUEUED
> EXEC
1) OK
2) OK
3) OK
127.0.0.1:6379> GET PROJECT
"JavaGuide3"
事务外部修改 WATCH 监视的 Key:
> SET PROJECT "JavaGuide"
OK
> WATCH PROJECT
OK
> SET PROJECT "JavaGuide2"
OK
> MULTI
OK
> GET USER
QUEUED
> EXEC
(nil)