目录
一、前言
事务这个名词我们在MySQL中就已经见到过了,那么提问一下事务是什么呢?如果HR这么问,你会怎么回答?
事务(Transaction) 是指 一组操作的集合 ,这些操作要么 全部成功执行 ,要么 全部失败回滚,不存在"部分成功"的中间状态。
一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其他命令插入。
二、Redis中的事务
之前已经学习过MySQL中的事务的概念,那么Redis中的事务和MySQL中的事务有什么区别呢?
Redis中事务的特性如下:
特性 | 说明 |
---|---|
单独的隔离操作 | Redis 的事务仅仅是保证事务里的操作会被连续独占的执行,redis 命令执行是单线程架构,在执行完事务内所有指令前是不可能再去同时执行其他客户端的请求的 |
没有隔离级别的概念 | 因为事务提交前任何指令都不会被实际执行,也就不存在 "事务内的查询要看到事务里的更新,在事务外查询不能看到" 这种问题了 |
不保证原子性 | Redis 的事务不保证原子性,也就是不保证所有指令同时成功或同时失败,只有决定是否开始执行全部指令的能力,没有执行到一半进行回滚的能力 |
排它性 | Redis 会保证一个事务内的命令依次执行,而不会被其它命令插入 |
三、Redis中事务命令
与MySQL一样,Redis中的事务也是使用命令来开启的。如下所示
号 | 命令及描述 |
---|---|
1 | DISCARD 取消事务,放弃执行事务块内的所有命令。 |
2 | EXEC 执行所有事务块内的命令。 |
3 | MULTI 标记一个事务块的开始。 |
4 | UNWATCH 取消 WATCH 命令对所有 key 的监视。 |
5 | WATCH key [key ...] 监视一个 (或多个) key,如果在事务执行之前这个 (或这些) key 被其他命令所改动,那么事务将被打断。 |
正常执行

放弃事务

全体连坐
这里指的是在Redis的事务中,写入指令集时,若其中任何一个指令的语法出现错误,在最后执行事务的时候都会直接报错,同时指令集中的所有指令都不会执行。

冤头债主
上面一则说的是在事务中指令发生语法错误报错的情况下,事务中的指令集一条都不会执行。那如果在执行事务中的指令集的时候没有语法错误,在执行事务之后报错会怎么样呢?
那就是冤有头债有主,对的指令执行,错误的指令不执行。

Watch监控
Redis使用Watch 来提供乐观锁定,类似于 CAS(Check-and-Set)
- 悲观锁
- 认为每次去拿数据都很认为别人会修改,所以每次拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁
- 乐观锁
- 认为每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据
- 提交版本必须 大于 记录当前版本才能执行更新
- CAS
- check-and-set(JUC中CAS操作相似)
我们先来了解一下乐观锁 和 悲观锁
维度 | 悲观锁(Pessimistic Lock) | 乐观锁(Optimistic Lock) |
---|---|---|
核心假设 | 认为数据一定会冲突,操作前先上锁。 | 认为数据大概率不冲突,操作时再检查冲突。 |
实现方式 | 通过 LOCK /UNLOCK 显式加锁(如 Redis 的 SETNX )。 |
通过 版本号 或 CAS(Check-and-Set) 实现无锁竞争。 |
优点 | 实现简单,冲突时阻塞等待,无"重试"成本。 | 无锁竞争,并发性能高,适合读多写少场景。 |
缺点 | 加锁/解锁开销大,并发高时易导致"死锁"或"饥饿"。 | 冲突时需重试,可能导致"活锁"(如重试策略不当)。 |
Redis 场景 | SETNX key lock + 过期时间实现分布式锁。 |
WATCH key + 事务实现 CAS 操作。 |

watch 命令是一种乐观锁的实现,Redis 在修改的时候会检测数据是否被更改,如果更改了,则执行失败,如下

如果使用 unwatch 命令放弃对键值的监控,则就可以在事务中更改。
总结
- 一旦执行了 exec 之前加的watch监控锁都会被取消掉
- 当客户端连接丢失的时候(比如退出连接),所有东西都会被取消监视。
感谢阅读!