1. WATCH关键点与实战要点
1.1 WATCH的工作原理与使用场景
在 Redis 事务模型中,WATCH 是实现乐观锁的核心操作。它可以对一个或多个键进行监视,一旦监视的键在事务执行前被其他客户端修改,后续的事务将被自动放弃,从而避免脏读和并发冲突。此机制的关键在于 监视集合 的变更检测,确保提交时数据的一致性。
在下单、库存扣减、限额控制等场景,使用 WATCH 可以让你先读取余额或库存,再执行更新,但只有在没有被外部修改的前提下才会提交。若监视的键被修改,执行失败,需要重新读取后再决定下一步。
常见的监听键包括商品库存键、账户余额键等,务必将与事务同一批逻辑相关的键放入 WATCH 中,以实现原子性前的冲突检测。
WATCH stock:items:42
2. MULTI指令:事务队列与入队命令
2.1 MULTI的开启与命令入队机制
在 Redis 事务模型中,MULTI 会开启一个事务块,之后在该块中的命令不会立即执行,而是被放入队列,等待 EXEC 一次性提交。这个过程确保了同一时刻对同一组键的操作要么全部执行,要么全部不执行,达到原子性效果。

如果在 MULTI 与 EXEC 之间,任意一个命令发生错误,Redis 仍会将整组命令作为一个事务去执行,直到执行阶段才会暴露错误信息。因此,设计者通常会在进入 MULTI 之前对命令进行严格的输入校验,以降低整体的失败率。
在使用场景中,WATCH 与 MULTI 搭配使用时,若被监视的键在事务提交前被外部修改,执行结果将会以空响应返回,表示事务已放弃,需要重新读取数据再决定下一步。
WATCH stock:100
MULTI
SET stock:100 60
INCR sales:today
EXEC
3. EXEC:原子性执行与结果处理
3.1 EXEC的结果含义与错误处理
在 EXEC 提交阶段,Redis 会对队列中的所有命令进行原子性执行,并返回一个包含每条命令回复的数组。如果在执行前发现 WATCH 的任意键已被修改,EXEC 将返回一个空的响应(null),表示该事务被放弃,需要重新读取并决定下一步。
如果没有监视键被修改,EXEC 会依次执行队列中的命令,并返回一个数组,其长度等于入队命令的数量,且每个元素对应相应命令的执行结果。此时事务对于所有相关键保持原子性。
在设计并发控制策略时,通常需要对 EXEC 的返回结果进行显式判断:若结果为 null,则表示冲突,需要重新获取数据并决定是否再次执行事务。
WATCH stock:100
MULTI
DECR stock:100
INCR sales:today
EXEC
4. DISCARD:放弃事务的正确时机
4.1 DISCARD的作用与注意点
当你在 MULTI 阶段发现某些条件不再满足,或者在执行前后需要取消整组操作时,可以使用 DISCARD 来放弃事务队列,并且结束对相关键的监视。DISCARD 之后,事务块中的命令将不会被执行,WATCH 的监视也会失效。
需要注意的是,DISCARD 不能部分执行某些命令,它会直接撤销整组入队命令,确保提交端不会产生部分成功的状态。对于需要回滚的场景,DISCARD 提供了一个简单的手段来保持一致性。
WATCH order:123
MULTI
SET order:123:status "cancelled"
DISCARD


