JavaGuide icon indicating copy to clipboard operation
JavaGuide copied to clipboard

Redis:WATCH 命令碰到 MULTI 命令时的不同效果

Open MarlonDML opened this issue 3 years ago • 2 comments

Redis-事务中提到 “WATCH 命令用于监听指定的键,当调用 EXEC 命令执行事务时,如果一个被 WATCH 命令监视的键被修改的话,整个事务都不会执行,直接返回失败”。这个说法似乎不太准确,这里以下面 3 个demo进行说明。

  1. 同一个session中,watch监视的key在multi之前被修改 image 根据测试结果可以得知,如果在 MULTI 之前被修改,那么这个事务不会被执行
  2. 同一个session中,watch监视的key在事务内部被修改 image 根据测试结果可以得知,如果在 MULTI 之后被修改或者说在事务内部被修改,那么这个事务还是会执行成功
  3. 同一个session中,watch监视的key在事务内部被修改,但是在事务提交之前被其他 session 修改 image

可以看出,场景一和场景三其实可以当成同一种情况;另外,WATCH 操作只是 session 级别的,不会影响其他 session,在同一个 session 中,对于同一个 Key ,在事务执行之前最多只能加一个 WATCHWATCH 监视的 Key 在事务内部被修改后,无论这个事务是否执行成功,这个 Key 上的 WATCH 就会自动取消(有兴趣的同学可以自行验证)可以得出结论:

只有当 WATCH事务 在同一个 session 里,并且被 WATCH 监视的Key,第一次被修改的操作在事务内部,这个事务才会执行成功

MarlonDML avatar Apr 30 '22 11:04 MarlonDML

WATCH 操作只是 session 级别的,不会影响其他 session,在同一个 session 中,对于同一个 Key ,在事务执行之前最多只能加一个 WATCHWATCH 监视的 Key 在事务内部被修改后,无论这个事务是否执行成功,这个 Key 上的 WATCH 就会自动取消(有兴趣的同学可以自行验证)可以得出结论:

感谢补充,受教了👍

Snailclimb avatar Sep 28 '22 01:09 Snailclimb

Redis-事务中提到 “WATCH 命令用于监听指定的键,当调用 EXEC 命令执行事务时,如果一个被 WATCH 命令监视的键被修改的话,整个事务都不会执行,直接返回失败”。这个说法似乎不太准确,这里以下面 3 个demo进行说明。

  1. 同一个session中,watch监视的key在multi之前被修改 image 根据测试结果可以得知,如果在 MULTI 之前被修改,那么这个事务不会被执行
  2. 同一个session中,watch监视的key在事务内部被修改 image 根据测试结果可以得知,如果在 MULTI 之后被修改或者说在事务内部被修改,那么这个事务还是会执行成功
  3. 同一个session中,watch监视的key在事务内部被修改,但是在事务提交之前被其他 session 修改 image

可以看出,场景一和场景三其实可以当成同一种情况;另外,WATCH 操作只是 session 级别的,不会影响其他 session,在同一个 session 中,对于同一个 Key ,在事务执行之前最多只能加一个 WATCHWATCH 监视的 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)

Snailclimb avatar Sep 28 '22 02:09 Snailclimb