首页/数据/数据库速查/批量执行三件套:Pipeline / 事务 / Lua 选型
Redis 运维与场景124 条

批量执行三件套:Pipeline / 事务 / Lua 选型

同样想减少往返或保证原子,三种机制语义完全不同:Pipeline 只是打包、MULTI/EXEC 是弱事务、Lua 是原子复合操作;按「是否要原子 + 是否有读判断写」来选。

数据库速查数据更新于 2026-10-13

三种批量机制怎么选

三种机制都常被用来减少网络往返,但语义完全不同:管道只是把多条命令打包发送,不保证原子;事务把命令排队后连续执行,中间不会被插入,但运行期出错不回滚;脚本以整段逻辑为原子单位执行,可以在服务端做读判断写。选型看两个问题:是否必须原子、是否需要先读后写。

基本信息

管道客户端打包多条命令一次发送,逐条返回结果
事务命令入队后提交时连续执行,支持监视实现乐观锁
脚本整段脚本原子执行,键通过参数显式传入
集群限制事务与脚本中的所有键必须同槽
阻塞代价脚本执行期间会阻塞其他请求,逻辑不宜过长

典型使用场景

  • 批量导入与缓存预热:只关心快、允许个别失败,用管道
  • 简单批量更新:几条命令需要连续执行不被插入,用事务
  • 库存扣减:先判断再写入且必须原子,用脚本
  • 限流计数:计数与设置过期需要原子完成,用脚本
  • 乐观锁更新:低冲突场景用监视加事务,冲突时重试

选型示例(库存大于零才扣)

选型示例(库存大于零才扣)
# 方案一:监视加事务,客户端需要写重试循环
WATCH stock:1
GET stock:1
MULTI
DECR stock:1
EXEC        # 期间键被改动则返回空结果,需要重试

# 方案二:脚本,一次调用完成判断与扣减
EVAL "if tonumber(redis.call('GET', KEYS[1]) or '-1') > 0 then return redis.call('DECR', KEYS[1]) else return -1 end" 1 stock:1

三种机制对比

机制原子性网络往返适用
管道无,可能部分成功一次批量读写与导入
事务命令间不被插入,出错不回滚一次简单批量加乐观锁
脚本整段原子一次读判断写的复合操作
单条命令天然原子一次能用单命令解决就别绕远
一句话选型:只图快用管道,逻辑简单且能接受重试用事务,并发正确性要求高用脚本。
脚本里不要写死循环或大量遍历:执行期间会阻塞实例上的其他所有请求,慢脚本影响的是整库。

易错点

  • 用管道实现扣库存:并发下超卖,管道不提供任何原子保证
  • 以为事务出错会回滚:语法错误整体拒绝,运行期错误只影响单条,其余照常执行
  • 把脚本当万能工具:越写越大,阻塞与维护成本同步上升
  • 集群下忽略同槽要求:事务与脚本中的键跨槽会直接报错

数据来源与参考

  • Redis 官方文档: Transactions
  • Redis 官方文档: Pipelining
  • Redis 官方文档: EVAL

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌