Skip to content

第11章:Redis 事务(保证多命令原子性)

11.1 事务的核心概念

Redis事务是一组命令的集合,它可以将多个命令打包,然后一次性、按顺序地执行这些命令。事务的核心特性是原子性:要么所有命令都执行成功,要么所有命令都不执行。

通俗理解:就像银行转账,从A账户扣钱和给B账户加钱这两个操作必须作为一个整体执行,不能只执行其中一个。

11.2 事务的使用命令

核心命令

  • MULTI:开启事务,后续命令会被加入事务队列而不立即执行
  • EXEC:执行事务队列中的所有命令
  • DISCARD:取消事务,清空事务队列
  • WATCH:监视一个或多个键,用于实现乐观锁

事务执行流程

  1. 执行 MULTI 开启事务
  2. 输入多个命令,这些命令会被加入事务队列
  3. 执行 EXEC 执行事务队列中的所有命令,或执行 DISCARD 取消事务

示例:基本事务操作

bash
# 开启事务
MULTI

# 添加命令到事务队列
SET user:1:name "zhangsan"
SET user:1:age 25
INCR user:1:login_count

# 执行事务
EXEC

11.3 事务中的错误处理

Redis事务中的错误分为两种类型:

1. 语法错误(在入队时检测)

当命令存在语法错误时,Redis会拒绝执行整个事务:

bash
MULTI
SET name "zhangsan"
SE  # 语法错误
EXEC  # 整个事务会被拒绝执行

2. 运行时错误(在执行时检测)

当命令语法正确但执行时出错(如对字符串执行自增操作),Redis会继续执行事务中的其他命令:

bash
MULTI
SET name "zhangsan"
INCR name  # 运行时错误:对字符串执行自增
SET age 25
EXEC  # 第一个和第三个命令会执行成功,第二个命令会失败

11.4 乐观锁与WATCH命令

WATCH命令用于实现乐观锁,它可以监视一个或多个键,当事务执行时,如果被监视的键被其他客户端修改,事务会被拒绝执行。

示例:使用WATCH实现乐观锁

bash
# 监视库存键
WATCH product:1001:stock

# 获取当前库存
GET product:1001:stock  # 假设返回 10

# 开启事务
MULTI

# 扣减库存
DECR product:1001:stock

# 增加销量
INCR product:1001:sales

# 执行事务
EXEC  # 如果期间库存被其他客户端修改,事务会失败

11.5 应用场景

  • 库存管理:扣减库存 + 增加销量,确保两个操作原子执行
  • 用户积分:扣除积分 + 记录消费,确保积分操作的一致性
  • 订单处理:创建订单 + 扣减库存,避免超卖

11.6 实操案例:实现库存扣减逻辑

需求分析

实现一个简单的库存扣减系统,需要保证以下操作的原子性:

  1. 检查库存是否充足
  2. 扣减库存
  3. 增加销量

实现步骤

  1. 初始化商品数据

    bash
    # 设置商品库存和销量
    SET product:1001:stock 10
    SET product:1001:sales 0
  2. 使用事务实现库存扣减

    bash
    # 监视库存键
    WATCH product:1001:stock
    
    # 获取当前库存
    local stock = tonumber(redis.call('GET', 'product:1001:stock'))
    
    if stock > 0 then
        # 开启事务
        redis.call('MULTI')
        # 扣减库存
        redis.call('DECR', 'product:1001:stock')
        # 增加销量
        redis.call('INCR', 'product:1001:sales')
        # 执行事务
        return redis.call('EXEC')
    else
        return {err = '库存不足'}
    end
  3. 测试并发场景

    • 打开两个Redis客户端
    • 同时执行库存扣减操作
    • 验证库存和销量的一致性

11.7 Redis事务与传统数据库事务的区别

特性Redis事务传统数据库事务
隔离级别无隔离级别,命令按顺序执行支持多种隔离级别
原子性部分支持(运行时错误不会回滚)完全支持
回滚不支持回滚支持回滚
锁机制乐观锁(WATCH)悲观锁/乐观锁

新手易错点

  • 误解Redis事务的原子性:运行时错误不会导致事务回滚
  • 未使用WATCH命令:在并发场景下可能导致数据不一致
  • 事务中使用非事务命令:某些命令(如INFO、CONFIG)在事务中会立即执行
  • 长时间占用事务:事务队列会占用内存,应避免长时间开启事务
  • 忽略事务执行结果:EXEC返回的数组包含每个命令的执行结果,应检查是否有错误

© 2026 编程马·菜鸟教程 版权所有