Redis 事务

Redis事务可以一次执行多个命令,本课学习事务的使用方法和注意事项。

什么是事务

事务是一组命令的集合,事务中的命令会按顺序执行,不会被其他命令打断。

MULTI → 命令1 → 命令2 → 命令3 → EXEC

基本命令

MULTI:开始事务

REDIS
MULTI
OK

EXEC:执行事务

REDIS
MULTI
OK

SET name "Alice"
QUEUED

SET age 25
QUEUED

EXEC
1) OK
2) OK

DISCARD:取消事务

REDIS
MULTI
OK

SET name "Bob"
QUEUED

DISCARD
OK

事务特性

命令队列

事务中的命令不会立即执行,而是进入队列:

REDIS
MULTI
OK

SET a 1
QUEUED

SET b 2
QUEUED

GET a
QUEUED

EXEC
1) OK
2) OK
3) "1"

原子性

事务中的命令要么全部执行,要么全部不执行:

REDIS
MULTI
OK

SET a 1
QUEUED

SET b 2
QUEUED

EXEC
1) OK
2) OK
⚠️ 注意: Redis事务不支持回滚。如果事务中某个命令执行失败,其他命令仍然会执行。

WATCH:乐观锁

WATCH用于监视键,如果键在事务执行前被修改,事务会被取消。

基本用法

REDIS
# 监视键
WATCH mykey
OK

# 开始事务
MULTI
OK

# 修改键
SET mykey "new_value"
QUEUED

# 执行事务
EXEC
(nil)  # 返回nil表示事务被取消(键被修改)

实现乐观锁

示例:乐观锁

BASH
# 客户端1
WATCH balance
GET balance
MULTI
SET balance 900
EXEC

# 客户端2(在客户端1执行EXEC之前)
SET balance 800
▶ 试一试

使用场景

1. 扣减库存

示例:扣减库存

BASH
# 扣减库存(原子操作)
MULTI
DECR stock:product:123
INCR sold:product:123
EXEC
▶ 试一试

2. 转账

示例:转账

BASH
# 转账:从用户A转100到用户B
MULTI
DECRBY balance:user:a 100
INCRBY balance:user:b 100
EXEC
▶ 试一试

3. 批量操作

示例:批量操作

BASH
# 批量设置多个键
MULTI
SET user:1:name "Alice"
SET user:1:age 25
SET user:1:email "alice@example.com"
EXEC
▶ 试一试

事务 vs 脚本

Lua脚本(推荐)

Lua脚本比事务更强大,支持条件判断和循环:

REDIS
# 原子操作:如果余额足够则扣减
EVAL "
  local balance = tonumber(redis.call('GET', KEYS[1]) or 0)
  if balance >= tonumber(ARGV[1]) then
    redis.call('DECRBY', KEYS[1], ARGV[1])
    return 1
  else
    return 0
  end
" 1 balance:user:a 100

事务 vs 脚本对比

特性 事务 Lua脚本
原子性
条件判断
循环
性能 较好 更好
复杂度 简单 较复杂

注意事项

⚠️ 不支持回滚: Redis事务不支持回滚,如果某个命令失败,其他命令仍然会执行。

⚠️ 命令错误: 语法错误会导致事务被取消,运行时错误不会影响其他命令。

💡 推荐使用Lua脚本: 对于复杂的原子操作,推荐使用Lua脚本。

❓ 常见问题

Q Redis事务支持回滚吗?
A 不支持。Redis事务不支持回滚,如果需要回滚功能,使用Lua脚本。
Q WATCH的作用是什么?
A WATCH用于实现乐观锁,监视键是否被修改,如果被修改则取消事务。
Q 事务中的命令是原子执行的吗?
A 是的。事务中的命令会按顺序执行,不会被其他命令打断。

📖 小节

📝 作业

  1. 事务练习: 使用MULTI/EXEC执行多个命令
  2. 乐观锁练习: 使用WATCH实现一个简单的乐观锁
  3. Lua脚本练习: 使用EVAL执行一个Lua脚本

下一课

下一课我们将学习 Redis 持久化,了解RDB和AOF两种持久化方式。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏