Redis:不只是缓存那么简单(十五)

发布时间:2026/7/14 23:19:30
Redis:不只是缓存那么简单(十五) 专栏Redis 修行录个人主页手握风云目录一、Redis 事务1.1. 基础概念1.2. 与 MySQL 事务核心区别1.3. 底层原理1.4. 核心命令1. MULTI2. EXEC3. DISCARD4. WATCH5. UNWATCH一、Redis 事务1.1. 基础概念Redis 事务与 MySQL 事务核心思路相似都是把多条操作命令绑定为一组实现批量统一执行。但 Redis 事务是弱化版事务不完整满足数据库标准 ACID 四大特性和 MySQL 事务存在巨大差异。1.2. 与 MySQL 事务核心区别原子性弱化MySQL 的原子性是指一组操作要么全部成功一旦失败则全部回滚恢复初始数据。Redis 的原子性仅保证命令连续批量执行不被插队没有回滚能力如果事务队列里某条命令语法报错整个事务全部不执行如果执行 EXEC 时某条命令运行报错其余合法命令仍会正常执行失败指令不会撤销数据也不会恢复初始状态。一致性不保证MySQL 的一致性保证事务执行前、执行后数据均合法有效不会出现非法中间状态依靠约束与回滚机制实现。Redis 无法保障一致性它不存在数据约束也没有回滚机制事务执行过程中有可能产生非法数据状态。隔离性完全不需要MySQL 存在多事务并发设计多种隔离级别解决并发冲突。Redis 单线程串行处理所有客户端请求同一时刻只会执行一组事务队列命令事务内操作会一次性连续跑完不会被其他客户端命令 “加塞”不存在事务并发场景因此不需要隔离性、没有隔离级别。持久性和事务无关MySQL 事务提交后数据永久落盘具备持久性。Redis 数据默认存储在内存持久化依靠 RDB/AOF 独立持久化方案控制事务本身不具备持久化能力两者互不绑定。1.3. 底层原理Redis 事务以服务器维护的专属事务队列作为核心载体。当通过 MULTI 命令开启事务后便进入入队阶段客户端提交的所有操作命令不会立刻执行而是仅存入事务队列服务器返回 QUEUED 标识就代表命令入队成功。后续分为执行和放弃两种分支发送 EXEC 命令时服务器会一次性批量执行队列内全部缓存命令事务正式生效发送 DISCARD 命令时则会直接清空事务队列队列中所有命令全部作废不会被执行。1.4. 核心命令1. MULTI# 开启事务初始化事务队列 MULTIMULTI 是事务的开启命令也是事务唯一的起始标识执行后会返回 OK完成事务队列初始化。执行该命令后客户端输入的所有读写指令不会立即执行只会存入事务队列返回 QUEUED 即代表命令成功入队只有先执行 MULTI客户端才能生成缓存命令的事务队列一般用于批量数据操作前初始化事务环境。2. EXEC# 提交事务批量执行队列内所有缓存命令 EXECEXEC 是事务提交命令也是唯一能批量执行队列缓存指令的入口。它分两种执行逻辑未搭配 WATCH 监控键时会串行完整执行队列内全部命令逐条返回每条指令的执行结果若提前用 WATCH 监控了指定键提交时会对比键的版本号一旦服务器上键的版本号发生变更EXEC 直接返回 nil队列中所有操作全部不执行。执行 EXEC 阶段 Redis 单线程会优先处理当前事务外部客户端请求需排队等待适用于事务全部操作编写完成后统一提交生效。3. DISCARD# 放弃未提交事务清空事务队列 DISCARDDISCARD 是放弃未提交事务的命令也是 Redis 在 EXEC 执行前撤销事务的唯一方式。执行后会直接清空事务队列里所有缓存指令直接终止本次事务并返回 OK不会对内存数据产生任何修改。由于 Redis 事务没有执行失败后的回滚机制当编写事务中途决定放弃本次批量操作时就可以使用 DISCARD 清空队列。4. WATCH# 乐观锁监控一组指定 key用于并发数据校验 WATCH key [key ...]WATCH 属于乐观锁监控命令必须在 MULTI 开启事务前执行核心作用是监控一组指定键完成并发数据校验。服务器会为每个键维护独立版本号键每被修改一次版本号就自动自增执行 WATCH 时会记录目标键当时的版本信息后续调用 EXEC 提交事务时会对比服务器当前键版本与事务记录版本两者不一致就代表键被其他客户端篡改整个事务直接失效所有命令不执行返回 nil。。该命令仅对当前客户端生效不存在阻塞行为多用于高并发场景防止事务执行期间目标键被其他客户端修改造成数据不一致。我们现在其中一个 Redis 客户端中执行事务 set k1 222再在另一个 Redis 客户端中不加事务执行 set k1 333再去执行 exec就会发现最终值是“222”。5. UNWATCH# 取消当前客户端所有 WATCH 监控的 key UNWATCHUNWATCH 是取消键监控的命令作为 WATCH 的逆向操作手动执行后会清除当前客户端所有通过 WATCH 绑定的键版本监控记录后续执行 EXEC 时不再做版本校验。