Redis 事务

面试官问:"Redis 有事务吗?"

小陈说:"有,MULTI 和 EXEC。"

面试官追问:"那 Redis 事务能回滚吗?"

小陈说:"...可以?"

面试官继续追问:"如果中间一条命令失败了,其他命令会怎样?"

小陈答不上来。

Redis 事务是面试中的高频题。这道题能说清楚 MULTI/EXEC/WATCH 的用法和 Redis 不支持回滚的原因的候选人,对 Redis 事务机制有深入理解。

一、Redis 事务基础 🔴

1.1 MULTI/EXEC

-- Redis 事务基本用法
MULTI  -- 开启事务
SET key1 value1
SET key2 value2
GET key1
INCR counter
EXEC  -- 执行事务中的所有命令

-- 结果:
-- 1) OK
-- 2) OK
-- 3) "value1"
-- 4) (integer) 1

1.2 Redis 事务的特点

-- Redis 事务 vs 数据库事务:
-- 数据库事务:ACID,原子性保证
-- Redis 事务:批量执行,不支持回滚

-- MULTI 开启事务后:
-- 命令进入队列,不立即执行
-- EXEC 执行队列中所有命令
-- DISCARD 清空队列,取消事务

1.3 ❌ 错误示范

候选人原话:"Redis 事务支持回滚。"

问题诊断:Redis 事务不支持回滚。如果事务中某条命令失败,其他命令仍然会执行。

候选人原话 2:"Redis 事务就是 MySQL 的事务。"

问题诊断:完全不同。MySQL 事务是 ACID 的,支持回滚;Redis 事务只是批量执行,不保证原子性(命令失败不回滚其他命令)。

【面试官心理】 这道题我会问"为什么 Redis 不支持回滚"。能说清楚"Redis 设计哲学是简单高性能,事务回滚开销大"的候选人,说明他理解了 Redis 的设计理念。

二、WATCH 实现乐观锁 🟡

2.1 WATCH 的用法

-- 场景:余额扣减(检查-然后-执行)
WATCH balance  -- 监视 balance 键
GET balance      -- 当前余额
-- 业务判断...

-- 如果在 EXEC 之前,balance 被其他客户端修改:
EXEC            -- 返回 nil(事务失败)
-- 客户端需要重试

-- 如果 balance 没有被修改:
EXEC            -- 执行所有命令,返回结果

2.2 WATCH 的实现原理

-- WATCH 使用乐观锁:
-- 1. WATCH 监视 key,记录监视版本号
-- 2. 其他客户端修改 key,版本号增加
-- 3. EXEC 执行时,检查版本号是否变化
-- 4. 版本号变了,EXEC 返回 nil
-- 5. 客户端需要重试整个事务

2.3 WATCH 取消

-- UNWATCH:取消所有 WATCH
UNWATCH

-- MULTI 执行后,所有 WATCH 自动取消
MULTI
SET key1 value1
EXEC  -- 自动 UNWATCH

三、Pipeline vs 事务 🟡

3.1 对比

维度Pipeline事务
命令打包多次网络往返 → 1 次多次网络往返 → 1 次
执行顺序顺序执行顺序执行
原子性无(失败不回滚)
监控不支持WATCH 乐观锁
回滚不支持不支持

3.2 Lua 脚本

-- Lua 脚本:Redis 原子执行
-- 整个 Lua 脚本是原子的,不会被打断

-- 示例:余额扣减
local balance = redis.call('GET', KEYS[1])
if tonumber(balance) >= tonumber(ARGV[1]) then
    redis.call('DECRBY', KEYS[1], ARGV[1])
    return redis.call('GET', KEYS[1])
else
    return -1  -- 余额不足
end

-- 执行:
EVAL "local balance = redis.call('GET', KEYS[1]) ..." 1 balance 100

四、生产选型 🟢

4.1 选型建议

-- 一般场景:Pipeline 足够
-- 批量命令,减少网络往返

-- 需要原子性:Lua 脚本
-- 复杂的检查-执行逻辑
-- 需要原子性的复合操作

-- 需要乐观锁:WATCH
-- 简单的检查-执行逻辑
-- 竞争不激烈的场景

【面试官心理】 Redis 事务是面试中的高频题。能说清楚 WATCH 的乐观锁实现、以及 Redis 事务和 Lua 脚本的区别的候选人,说明他对 Redis 的并发控制有深入理解。


级别考察重点期望回答
P5基本用法MULTI/EXEC
P6深入机制WATCH 乐观锁、不支持回滚的原因
P7选型Pipeline vs 事务 vs Lua