TRANSACTION 是 Redis 的事务机制,通过 MULTI、EXEC、DISCARD 和 WATCH 命令实现一组命令的原子性执行。
MULTI
EXEC
DISCARD
WATCH key [key ...]
UNWATCH
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| key | String | 是(WATCH) | 要监控的键名,支持多个 |
OK,进入事务状态(nil),事务不执行OKOKOK> MULTI
OK
> SET balance 100
QUEUED
> DECRBY balance 30
QUEUED
> EXEC
1) OK
2) (integer) 70
> MULTI
OK
> SET tempkey "temp"
QUEUED
> GET tempkey
QUEUED
> DISCARD
OK
> GET tempkey
(nil)
> WATCH balance
OK
> MULTI
OK
> DECRBY balance 50
QUEUED
> EXEC
(nil) -- 执行期间 balance 被其他客户端修改,事务放弃
> MULTI
OK
> HSET user:1 name "Alice" age 30
QUEUED
> ZADD leaderboard 100 "Alice"
QUEUED
> EXPIRE user:1 3600
QUEUED
> EXEC
1) (integer) 2
2) (integer) 1
3) (integer) 1
| 错误 | 原因 | 解决 |
|---|---|---|
| EXEC without MULTI | 未开启事务就执行 EXEC | 先调用 MULTI |
| ERR WATCH inside MULTI is not allowed | 在 MULTI 内部调用 WATCH | WATCH 必须在 MULTI 之前执行 |
| ERR EXEC without MULTI | 未开启事务 | 确保 EXEC 前有对应的 MULTI |
Q1: Redis 事务和关系型数据库事务有什么区别? A: Redis 事务没有回滚机制,仅保证命令打包原子执行。命令入队后即使语法错误,EXEC 时其他正确命令仍会执行。
Q2: WATCH 后如果键被修改,EXEC 会返回什么?
A: 返回 (nil)(空回复),表示事务因乐观锁冲突被放弃,客户端应重试。
Q3: 事务中的命令会立即执行吗? A: 不会。MULTI 后所有命令进入队列,返回 QUEUED,直到 EXEC 时才一次性顺序执行。
Q4: 事务和 Lua 脚本怎么选? A: 简单命令组合用事务;需要条件判断、循环、复杂计算时用 Lua 脚本,脚本天然原子执行且更灵活。