Redis Lua脚本保证库存扣减与记录写入原子性的设计
库存扣减最怕两件事被拆开:可用库存已经减掉,但请求记录没有写入;或者两个客户端都读到“还有库存”,随后各自扣减。Redis Lua 的合适边界是把校验、扣减和记录写入放进同一次脚本执行,并让调用方只传入显式的键和业务参数。这样解决的是 Redis 内部操作的原子执行,不等于给跨系统支付、发货或数据库写入提供回滚。
- 库存键和请求记录键都放进
KEYS,数量、请求号和时间放进ARGV。 - 先校验参数、已有请求和库存,再执行
DECRBY与HSET,避免错误发生在写操作之后。 - 返回码要区分成功、重复请求、库存不足和参数错误;业务副作用仍需应用层补偿。
Redis 官方地址:https://redis.io/docs/latest/
先把库存和请求记录设计成同一组键
示例使用一个商品维度的库存字符串和一个请求记录 Hash:stock:{sku-42}:available 保存剩余数量,stock:{sku-42}:orders 以 request_id 为 field 保存扣减结果。两者共享 {sku-42} hash tag,放到 Redis Cluster 时会落在同一 hash slot;脚本不需要根据库存值拼接新的键名。
| 输入 | 示例 | 语义 |
|---|---|---|
| KEYS[1] | stock:{sku-42}:available | 可扣减库存,字符串整数 |
| KEYS[2] | stock:{sku-42}:orders | 请求记录 Hash |
| ARGV | request_id、quantity、now | 业务参数,不是键名 |

把校验放在扣减之前,再让两个写操作共享原子边界
下面的脚本用 request_id 做幂等记录。已有记录直接返回重复,不再重复扣减;库存不足返回当前库存;只有所有前置检查通过,才执行扣减和记录写入。代码中的两个键都来自 KEYS,不要在脚本里把 ARGV 拼成键名。
-- KEYS[1] 是库存字符串,KEYS[2] 是请求记录 Hash -- ARGV[1] 请求号,ARGV[2] 扣减数量,ARGV[3] 记录时间 local request_id = ARGV[1] local quantity = tonumber(ARGV[2]) local now = ARGV[3] -- 先拒绝空请求、非正数量和重复请求,避免进入写阶段 if not request_id or request_id == '' or not quantity or quantity
调用时把键数量写成 2,后面依次传两个键和三个普通参数:
# 两个 KEY 必须显式列出;request_id、数量和时间属于 ARGV
redis-cli EVAL "$(cat stock.lua)" 2 \
stock:{sku-42}:available stock:{sku-42}:orders \
req-20260920-0007 2 1789891200
Redis 文档说明 Lua 脚本执行期间会阻塞其他服务器活动,因此两个写入不会被另一个客户端插入。这里仍要保留一个重要边界:脚本原子执行不是事务回滚;如果把不可预测的命令错误放在扣减之后,之前已经完成的写入可能留下。生产脚本应先验证类型、参数和键结构,并尽量保持短小。

返回码要让调用方能处理重复和失败
建议把返回值的第一个元素固定为机器可判断的码:1 表示本次扣减成功,2 表示相同请求号已经处理过,0 表示库存不足,-1 表示参数或库存初始化错误。第三个元素统一返回剩余库存,调用方无需再发一次 GET 才能展示结果。
| 返回码 | 调用方动作 | 不能做什么 |
|---|---|---|
1 | 记录成功并继续业务流程 | 不要再次扣减 |
2 | 按幂等成功处理或查询原记录 | 不要把重复请求当库存不足 |
0 | 提示无库存或进入候补流程 | 不要重试同一请求制造热循环 |
-1 | 告警并修复参数或初始化 | 不要静默吞掉脚本错误 |
上线前检查集群键位、记录保留和脚本耗时
上线前至少检查四项:库存键是否为整数、请求号是否真正唯一、两个键是否使用相同 hash tag、请求记录是否有清理策略。记录 Hash 如果无限增长,会把幂等保护变成新的内存问题;如果过早删除,重复请求又可能被当成新请求。还要监控脚本耗时,避免在 Lua 中遍历大量订单或调用外部系统。
常见问题
Lua 脚本能保证数据库和 Redis 同时成功吗?
不能。脚本只覆盖 Redis 内部的命令边界;数据库、支付和消息系统需要事务、幂等事件或补偿流程。
为什么不能把库存键名放在 ARGV 里?
Redis 要求脚本访问的键显式列在 KEYS 中,这对集群路由和脚本可分析性都更安全。ARGV 应只承载数量、请求号等普通参数。
重复请求返回成功还是重复更合适?
建议返回独立的重复码,并带回当前库存或原记录摘要。这样调用方可以把“已完成”与“本次新扣减”区分开,避免重复发货。
商汤Seko能不能用于内容工作室多项目排期?看项目隔离、素材复用与审核责任
- 上一篇
- 商汤Seko能不能用于内容工作室多项目排期?看项目隔离、素材复用与审核责任
- 下一篇
- Go http.Transport空闲连接失效时的回收参数配置
-
- 数据库 · Redis | 2小时前 |
- Redis Hash与JSON字符串存储对象的选择边界
- 476浏览 收藏
-
- 数据库 · Redis | 3小时前 | Redis ZSET延迟队列 Redis有序集合 Redis重复任务 ZADD NX 延迟任务重试
- Redis ZSET实现延迟队列并控制重复任务的做法
- 489浏览 收藏
-
- 数据库 · Redis | 4小时前 |
- Redis XAUTOCLAIM批量接管失联消费者消息的实现方法
- 485浏览 收藏
-
- 数据库 · Redis | 6小时前 | Redis · 消息队列 · redis streams XREADGROUP XACK
- Redis Stream用消费组实现可重试任务队列的方案
- 349浏览 收藏
-
- 数据库 · Redis | 7小时前 | Redis ·
- Redis Sentinel读取主从切换后的服务发现结果的实现方法
- 236浏览 收藏
-
- 数据库 · Redis | 8小时前 | Redis · BitMap · BITFIELD Redis Bitmap Redis bitmap偏移 SETBIT GETBIT
- Redis bitmap计算位图偏移并避免越界的实现方法
- 130浏览 收藏
-
- 数据库 · Redis | 10小时前 |
- Redis HyperLogLog用近似结构估算去重计数的实现方法
- 364浏览 收藏
-
- 数据库 · Redis | 11小时前 |
- Redis Pub/Sub重连后恢复订阅关系的实现方法
- 309浏览 收藏
-
- 数据库 · Redis | 12小时前 |
- Redis Pipeline区分批量发送与命令执行错误的实现方法
- 354浏览 收藏
-
- 数据库 · Redis | 13小时前 | Redis · redis maxmemory maxmemory-policy evicted_keys INFO stats
- Redis 内存淘汰变更策略后观察淘汰计数的实现方法
- 223浏览 收藏
-
- 数据库 · Redis | 16小时前 | 数据安全 · 性能排查 · appendfsync AOF重写 BGREWRITEAOF Redis AOF Redis持久化 Redis延迟排查
- Redis AOF理解重写期间的磁盘与延迟的实现方法
- 218浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 135次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 200次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 146次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 126次使用
-
- CMMLU
- 深入了解CMMLU中文评估基准,涵盖67个学科主题,提供数据集下载、Zero-shot/Five-shot评估方法及排行榜,助力优化中文语言模型性能。
- 111次使用
-
- Go语言中通过Lua脚本操作Redis的方法
- 2023-01-07 234浏览
-
- GO的锁和原子操作的示例详解
- 2023-02-25 141浏览
-
- Go sync/atomic.Uint64 计数器怎么做并发统计:读写边界、溢出与快照一致性
- 2026-08-27 466浏览
-
- Go atomic.Int64 和旧式原子函数怎么选择
- 2026-09-10 130浏览
-
- Go 问答:sync.Once 为什么能保证只执行一次,多协程下怎么复用
- 2026-06-15 142浏览

