三种批量机制怎么选
三种机制都常被用来减少网络往返,但语义完全不同:管道只是把多条命令打包发送,不保证原子;事务把命令排队后连续执行,中间不会被插入,但运行期出错不回滚;脚本以整段逻辑为原子单位执行,可以在服务端做读判断写。选型看两个问题:是否必须原子、是否需要先读后写。
基本信息
| 管道 | 客户端打包多条命令一次发送,逐条返回结果 |
|---|---|
| 事务 | 命令入队后提交时连续执行,支持监视实现乐观锁 |
| 脚本 | 整段脚本原子执行,键通过参数显式传入 |
| 集群限制 | 事务与脚本中的所有键必须同槽 |
| 阻塞代价 | 脚本执行期间会阻塞其他请求,逻辑不宜过长 |
典型使用场景
- 批量导入与缓存预热:只关心快、允许个别失败,用管道
- 简单批量更新:几条命令需要连续执行不被插入,用事务
- 库存扣减:先判断再写入且必须原子,用脚本
- 限流计数:计数与设置过期需要原子完成,用脚本
- 乐观锁更新:低冲突场景用监视加事务,冲突时重试
选型示例(库存大于零才扣)
选型示例(库存大于零才扣)
# 方案一:监视加事务,客户端需要写重试循环
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三种机制对比
| 机制 | 原子性 | 网络往返 | 适用 |
|---|---|---|---|
| 管道 | 无,可能部分成功 | 一次 | 批量读写与导入 |
| 事务 | 命令间不被插入,出错不回滚 | 一次 | 简单批量加乐观锁 |
| 脚本 | 整段原子 | 一次 | 读判断写的复合操作 |
| 单条命令 | 天然原子 | 一次 | 能用单命令解决就别绕远 |
一句话选型:只图快用管道,逻辑简单且能接受重试用事务,并发正确性要求高用脚本。
脚本里不要写死循环或大量遍历:执行期间会阻塞实例上的其他所有请求,慢脚本影响的是整库。