活动名额被抢超了:用 Redis Lua 脚本加分布式锁把报名扣减做成原子操作

简介: 本文详解商协会活动报名系统库存扣减的演进:从数据库“查-判-更”超卖,到乐观锁重试、Redis DECR负数问题,最终通过原子化Lua脚本(含库存校验、去重、扣减、记名)彻底解决。辅以分布式锁防重复提交、异步落库+回滚+对账机制,实现零超卖、P99降至60ms,逻辑清晰可追溯。(239字)

商协会的活动报名有个特点:名额有限、开放时间集中。一场限五十人的活动,通知下午三点发出去,三点零几分流量就上来了。早先扣减逻辑是查库存、判断、更新三步,压测一跑就超卖——五十个名额卖出去五十六个。

这篇把改造过程整理一遍,重点不是贴代码,而是每一步为什么这么改。

第一版是纯数据库操作:SELECT 查剩余名额,大于零就 UPDATE 减一。并发下"查再改"不是原子的,两个请求同时查到还剩一个,都会去减。第二版加乐观锁,UPDATE 时带 stock > 0 的条件,用影响行数判成败。并发不高时够用,但冲突多了大量请求要重试,响应时间不可预测。

第三版换成 Redis,直接用 DECR 扣库存。这版有两个新毛病:DECR 会减成负数,只能事后发现;而且不知道是谁抢到的,补记录操作和扣减不是原子的,失败就出现"扣了库存但没报名记录"。

最终版把整个判断和扣减塞进一段 Lua。Redis 执行 Lua 是单线程的,脚本内多条命令不会被打断,天然原子。

-- KEYS[1]: 活动库存键    KEYS[2]: 已报名会员集合
-- ARGV[1]: 会员ID        ARGV[2]: 集合过期时间(秒)
-- 返回值: 1 成功 / 0 已售罄 / -1 库存未初始化 / -2 重复报名
local stock = tonumber(redis.call('GET', KEYS[1]))
if stock == nil then return -1 end
if stock <= 0 then return 0 end
if redis.call('SISMEMBER', KEYS[2], ARGV[1]) == 1 then return -2 end
redis.call('DECR', KEYS[1])
redis.call('SADD', KEYS[2], ARGV[1])
redis.call('EXPIRE', KEYS[2], tonumber(ARGV[2]))
return 1

判库存、判重、扣减加记名,一次调用完成。判重放在集合里做,同一会员重复提交直接返回 -2,不用依赖数据库的联合索引兜底。

服务端用 EVALSHA 调用,脚本首次加载后复用 SHA,减少网络传输。NOSCRIPT 报错时重新加载再执行一次即可。

服务端用 EVALSHA 调用,脚本首次加载后复用 SHA,减少网络传输,遇到 NOSCRIPT 报错时重新加载再执行一次即可。调用侧还包了一层分布式锁:锁的粒度是会员加活动,用 SET NX PX 拿锁,拿不到就返回并发冲突;执行完在 finally 里释放,释放前用 Lua 比对令牌,避免误删其他请求持有的锁。扣减成功后异步写库,写库失败要把库存加回去。

几个坑值得单独说。

一是锁不是用来扣库存的。库存扣减已由 Lua 保证原子,锁只挡同一会员在极短时间内的重复点击,粒度是会员加活动,不是整个活动。把锁加到活动上等于把并发串行化,跟没上 Redis 一样。

二是锁要带过期时间,释放时比对令牌。设了值不设过期,进程崩了锁就永远在那儿;释放时不比对令牌,可能删掉别的请求刚拿到的锁。这两条是老规矩,线上出问题的多半还是它们。

三是异步落库失败必须回滚。扣减成功、写库失败不 INCR 回去,名额就凭空少一个。回滚本身也可能失败,所以还要一层对账:定时任务比对 Redis 库存和数据库报名数,不一致时以数据库为准。

四是库存初始化要有保护。活动创建时把名额写进 Redis,这步失败或者 Redis 重启后键丢了,脚本返回 -1。这时回落到数据库查真实报名数,重设库存键再走一次流程,别直接把请求拒掉。

五是别把 Redis 当可靠存储。它是加速层,最终以数据库为准,报名记录入库时仍然依赖数据库的联合约束防重复。

改造之后压测,五十个名额并发抢购超卖为零,接口 P99 从四百多毫秒降到六十毫秒左右。收获不在性能,而在逻辑变得可解释:库存在哪、谁抢到了、失败原因是什么,每条都有出处。

我们这边在跑的商会管理系统叫未来漫城·商会互联平台,活动报名这块就是这套实现,热门活动开放报名时不再需要人为盯着库存。

最后提醒一句:Lua 脚本要保持短小。脚本执行期间 Redis 单线程阻塞,里面放循环或慢操作会拖垮整个实例。像"批量扣减多个活动"这种需求,宁可调用多次,也不要写成一次大循环。

相关文章
|
9月前
|
缓存 NoSQL 测试技术
库存合并扣减:一种基于分布式缓存的强一致性热点库存扣减方案
本文介绍了一种基于Redis分桶扣减与DB合并提交的强一致库存扣减方案,适用于热点商品高并发抢购场景。通过Redis实现高性能扣减计数,结合数据库明细保障数据准确,既避免超卖少卖,又显著提升TPS与系统稳定性,有效支撑直播等大流量业务需求。
库存合并扣减:一种基于分布式缓存的强一致性热点库存扣减方案
|
2天前
|
人工智能 JSON 编解码
【2026最新版】ComfyUI本地部署教程,新手也能看懂!
ComfyUI是本地运行的AI绘画工具,采用节点式工作流设计:通过拖拽连接“加载模型”“提示词编码”“采样”“解码”等模块,实现高度可控的文生图。新手推荐使用秋叶整合包,一键启动、内置模型管理与插件安装器,轻松上手。(239字)
|
7天前
|
人工智能 自然语言处理 数据挖掘
阿里云千问办公企业积分包:多少钱、怎么买、怎么用?
千问办公是阿里推出的AI办公平台,支持自然语言驱动的数据分析、PPT生成、视频剪辑、网页搭建等。企业版席位每月附赠2000积分,额度不足时可增购积分包(100元起/2000分,有效期12个月),需配合有效席位使用。(239字)
|
11天前
|
人工智能 PyTorch 云栖大会
亮点抢先看!AMD、中兴通讯等企业大咖解码下一代 OS|2026 云栖大会
一览来自 AMD、中兴通讯、阿里云、英特尔,以及上海交通大学等企业/高校专家的精彩金句和重磅议题。
|
12天前
|
存储 人工智能 自然语言处理
阿里云千问办公 QwenWork详细介绍:产品核心能力、典型场景、价格及常见问题解答
阿里云千问办公(QwenWork)是通义实验室推出的AI原生办公平台,依托Qwen3.8大模型,支持自然语言生成PPT、Excel、网页、视频等;具备浏览器自动化、深度检索、钉钉/飞书集成、定时任务及多端协同能力,真正实现“对话即交付”。
407 2
|
16天前
|
人工智能 IDE 数据挖掘
办公还是开发?千问办公QwenWork、Qoder CN、QoderTeams能力拆解与落地实战教程
随着AI智能体工具持续迭代,面向办公、研发的多款产品功能存在部分重叠,很多企业和个人使用者容易混淆千问办公(QwenWork)、Qoder CN、QoderTeams三款产品。不少用户误以为三款产品能力可以互相替代,甚至以为账号、积分资源可以互通,采购之后才发现产品能力与自身岗位业务不匹配,造成预算浪费。千问办公主打通用职场办公自动化;Qoder CN(原通义灵码)是面向开发者的AI编码智能体全家桶;QoderTeams并不是独立软件,而是Qoder CN体系下面向研发小组的企业团队订阅套餐。三者底层基座同源,但产品定位、目标人群、集成生态、计费体系、数据合规能力完全不同。本文完整拆解三款产品
221 2
|
2月前
|
存储 JavaScript 安全
dsh 拆解系列 Vol.01:没有特权内核的 Agent 运行时
DeepSeek Harness(dsh)是DeepSeek开源的Agent运行时框架,秉持“一切皆插件”理念,将模型适配器、工具、会话、主循环等全部解耦为可配置、可替换、可卸载的插件,基于Cordis元框架实现时空可组合性。当前v0.1.0-rc.7为开发者预览版,MIT协议,强调工程可扩展性而非仅功能堆砌。
313 2
dsh 拆解系列 Vol.01:没有特权内核的 Agent 运行时
|
26天前
|
人工智能 自然语言处理 API
阿里云百炼Token Plan和Coding Plan有什么区别?CodingPlan在哪购买?个人开发者选哪个省钱?
阿里云百炼两大订阅:Token Plan按Credits计费,支持多模态模型及各类AI工具;Coding Plan为固定月费¥200(限时首月¥39.9),仅限交互式编程,限量抢购。官方推荐Token Plan,适用更广、灵活性更强。在阿里云百炼官网:https://t.aliyun.com/U/fPVHqY 免费领取千万Tokens
|
27天前
|
人工智能 IDE API
阿里云Qoder CN服务平台完整功能解读:从本地IDE配置、终端CLI使用、云端部署到开放API全链路解读
软件研发工作包含需求拆解、代码编写、单元测试、故障排查、文档撰写、项目重构等大量重复性工作。传统开发模式下,开发者需要手动翻阅项目源码、查阅接口文档、调试报错堆栈,大型项目代码体量庞大,新人熟悉项目架构要耗费大量时间。普通代码补全工具只能完成单行片段生成,无法理解完整工程上下文,不能独立处理跨多文件的复杂开发任务。Qoder CN,前身是通义灵码,是面向软件研发全流程的AI智能体产品套件,不再局限于简单的代码片段补全,而是以编程Agent智能体为核心,覆盖本地桌面开发、终端命令行、云端托管运行、数字员工等多种形态,深度对接百炼平台Coding Plan、Token Plan订阅体系,支持Qwe
335 1
|
2月前
|
运维 Linux iOS开发
PowerShell怎么用?PowerShell下载安装使用教程(全网最详细)
PowerShell是微软推出的跨平台命令行与脚本工具,功能远超CMD:内置上千cmdlet、支持管道组合、兼容Windows/macOS/Linux。适用于运维、开发及自动化场景,最新版7.6.5可与系统自带5.1共存。(239字)

热门文章

最新文章