活动名额被抢超了:用 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与系统稳定性,有效支撑直播等大流量业务需求。
库存合并扣减:一种基于分布式缓存的强一致性热点库存扣减方案
|
11天前
|
人工智能 JSON 安全
Windows 下 Claude Code 落地全指南:从安装配置到避坑优化
本文详解Windows下Claude Code的完整落地指南:涵盖WinGet/脚本/手动三种安装方式、对接阿里云Qwen等国内模型的配置、全界面与AI输出中文化、权限弹窗优化、长上下文卡顿(Stalled/Brewed)的性能调优,所有配置代码可直接复制使用,助你快速避坑、高效开发。(239字)
192 3
Windows 下 Claude Code 落地全指南:从安装配置到避坑优化
|
16天前
|
存储 弹性计算 固态存储
阿里云服务器多少钱一年?轻量200M带宽38元/年、ECS服务器99元/年、2核4G5M带宽199元/年
本文详解2026年阿里云服务器最新价格:轻量应用服务器200M带宽仅38元/年,ECS经济型99元/年,企业级2核4G+5M带宽199元/年;涵盖包年包月、按量付费、抢占式实例三种计费模式,并解析ECS实例规格、带宽及系统盘详细收费标准。(239字)
|
1月前
|
人工智能 自然语言处理 API
阿里云百炼Token Plan和Coding Plan有什么区别?CodingPlan在哪购买?个人开发者选哪个省钱?
阿里云百炼两大订阅:Token Plan按Credits计费,支持多模态模型及各类AI工具;Coding Plan为固定月费¥200(限时首月¥39.9),仅限交互式编程,限量抢购。官方推荐Token Plan,适用更广、灵活性更强。在阿里云百炼官网:https://t.aliyun.com/U/fPVHqY 免费领取千万Tokens
|
1月前
|
人工智能 IDE API
阿里云Qoder CN服务平台完整功能解读:从本地IDE配置、终端CLI使用、云端部署到开放API全链路解读
软件研发工作包含需求拆解、代码编写、单元测试、故障排查、文档撰写、项目重构等大量重复性工作。传统开发模式下,开发者需要手动翻阅项目源码、查阅接口文档、调试报错堆栈,大型项目代码体量庞大,新人熟悉项目架构要耗费大量时间。普通代码补全工具只能完成单行片段生成,无法理解完整工程上下文,不能独立处理跨多文件的复杂开发任务。Qoder CN,前身是通义灵码,是面向软件研发全流程的AI智能体产品套件,不再局限于简单的代码片段补全,而是以编程Agent智能体为核心,覆盖本地桌面开发、终端命令行、云端托管运行、数字员工等多种形态,深度对接百炼平台Coding Plan、Token Plan订阅体系,支持Qwe
415 1
|
2月前
|
存储 JSON 数据可视化
基于YOLO11的航拍路面杂物抛洒物检测:从数据标注到云上训练实践
本文介绍基于YOLO11的航拍路面杂物检测全流程实践,涵盖数据标注、云上训练、模型评估与工程落地。针对小目标多、背景复杂等难点,提出高分辨率输入、多尺度训练与标注质量闭环等优化策略,助力无人机智能巡检高效落地。(239字)
|
2月前
|
人工智能 自然语言处理 API
从入门到精通阿里云千问:模型矩阵、免费额度、API代码调用与企业落地指南
AI产业落地的浪潮下,自研通用大模型已经成为数字化转型的核心基础设施。阿里云千问,官方名称通义千问,代号Qwen,是阿里云完全自主研发的全栈式大模型家族,并非单一文本模型,而是覆盖纯文本、代码、图像、音频、视频、行业垂直场景的完整产品矩阵,统一依托阿里云百炼大模型服务平台对外提供模型调用、微调、智能体开发、私有知识库构建、应用一键部署等全链路MaaS服务。当前主力迭代版本为Qwen3.7系列,形成旗舰、均衡、轻量、多模态、代码专用五大分支模型,在中文理解、超长上下文推理、自主智能体执行、多模态统一解析四大维度具备国产头部水准,同时搭配免费试用、按量计费、Token Plan订阅、长期节省计划四
1139 4
|
2月前
|
人工智能 IDE 安全
阿里云Qoder CN全解析:AI编码智能体全场景功能深度指南
阿里云Qoder CN(原灵码)是阿里云推出的全栈式AI智能体产品系列,定位为覆盖编码、办公、终端、云端的一体化AI开发与协作平台,以多模态编程、智能体自主执行、全端覆盖、企业级安全合规为核心优势,深度适配国内开发者与企业的研发、办公、运维全流程需求。平台内置多模型自由切换、工程级代码处理、智能体任务编排、多模态交互、企业知识库集成等核心能力,提供桌面IDE、JetBrains插件、CLI终端、云端智能体、桌面办公助手等全形态产品,实现“一个账号、全场景覆盖、Credits共享”的一体化体验,是国内领先的AI编码与智能体协作平台。本文从产品矩阵、核心能力、全端接入、实战代码、企业级特性、订阅方
645 2
|
3月前
|
Cloud Native Java Spring
ACK + GraalVM Native Image 实战:Spring Boot 3.4 从500ms到50ms启动的云原生 Java
K8s 里 Java 应用启动要 8 秒,HPA 弹性扩容等到流量早过去了——这是我们团队在 ACK 上部署 Spring Boot 微服务时遇到的真实困境。引入 GraalVM Native Image 后,启动时间从 8 秒降到 50ms,内存从 512MB 降到 64MB,镜像体积缩减 70%,Serverless 场景完美适配。本文从 Java 云原生困境出发,详解 GraalVM Native Image 编译原理、Spring Boot 3.4 适配全流程(运行时代理注册、序列化配置、动态代理、资源文件)、ACK 多架构镜像构建与部署实战
|
3月前
|
人工智能 前端开发 小程序
AI 编程工具排名 2026:7 款主流横评(国产 + 海外实测)
AI 编程工具有哪些?哪个 AI 写代码最强?2026 年 AI 编程工具排名横评:Cursor、Bolt.new、Lovable、v0、秒悟 Meoo、通义灵码。从场景适配度、价格、商用合规、中文支持 6 个维度实测。
11170 0