秒杀场景Redis做预扣减,问题在哪里?

Redis 做预扣减,你以为很稳,其实坑不少

秒杀场景下的库存扣减

秒杀系统的核心就是库存扣减。用户下单 → 库存减一 → 库存为零就卖完了。

问题在于:数据库扛不住高并发。几万人同时抢几百件商品,直接去 UPDATE 数据库,行锁、死锁、连接池爆满分分钟教做人。

所以常规做法是用 Redis 做预扣减------库存提前加载到 Redis,扣减发生在内存里,扛得住高并发。订单真正落库的时候再同步减数据库。

这个方案确实能抗住流量,但你得知道它有几个坑。


坑一:缓存和数据库不一致

Redis 里的库存扣了,但数据库还没来得及更新。

这时候如果消费端出了问题------比如扣了 Redis 库存,但下单失败了、支付超时了、用户取消了------Redis 里的库存就白白少了一份。

解决方式:任何导致订单失败的异常路径,都必须把 Redis 库存加回去。

库存回滚不是可选的,是必须的。漏了任何一个回滚分支,仓库里就凭空少了几个商品,少卖就少赚了。


坑二:少卖------抢到了不付钱,想买的抢不到

这是秒杀场景的一个经典困境:

A 抢到了最后一件,锁了库存。但 A 长时间不付款,订单卡在那。

B 是真心想买的,但一看没库存了,走了。

过了一阵 A 又取消订单了,库存加回去,但 B 已经不在了。最后活动结束,库存还剩几件,没人买走------少卖了。

解决方式:秒杀商品的订单有效期要大幅缩短。

普通商品可能给你 30 分钟付款,秒杀活动直接缩到 2 分钟。超时未付款自动取消订单,库存立刻回 Redis,让真正想买的人有机会。反正这几分钟你都决定不了要不要买,那就把机会让给别人。


坑三:Redis 宕机,库存数据丢了

Redis 是内存数据库,如果秒杀活动前 Redis 突然挂了,重启后内存里什么都没有。

你把库存从数据库重新加载进去?问题是------秒杀过程中已经扣减了多少,这个状态丢了。你只能从零重新开始,或者从数据库里算差值,手忙脚乱。

两个应对措施:

第一,秒杀开始前调高 AOF 刷盘频率。 默认可能是每秒刷一次,秒杀期间可以改成每条写命令都刷(appendfsync always),尽量保证数据落地。虽然性能会差一点,但压秒杀的流量 Redis 扛得住,丢数据的代价更大。

第二,上主从 + 哨兵。 主节点挂了自动切从节点,秒杀不能停。但要特别注意------异步复制下主挂了可能会有极少量数据没同步到从节点,这是 Redis 主从机制的天花板,没法完全避免。


坑四:库存 Key 变成热 Key,打爆单节点

所有用户的抢购请求都打在同一个库存 Key 上。

正常场景 Redis 完全没压力,但秒杀的第一秒,几万 QPS 全怼在同一个 Key 上,这个节点就成为了瓶颈。Redis 是单线程处理命令,一个 Key 上去了其他命令排队等,整个实例的响应延迟都被拖高。

缓解办法:

静态数据下沉到本地缓存。 商品图片、描述、封面这些不会变的东西,扔到 Caffeine 里,别每次都从 Redis 查。给库存扣减腾出带宽。

库存拆分。stock:10086 这一个 Key 拆成 10 个:stock:10086:1stock:10086:2...每个 Key 存一部分库存,请求随机打散到不同 Key 上。

但拆分有个隐藏成本------某个分片库存先耗尽了,你得立刻把请求路由到其他分片,否则用户抢着抢着发现明明总库存还有,但就是提示"已售罄"。这个路由逻辑搞复杂了反而容易出错,一般只有在 QPS 真的打到单节点天花板的时候才考虑拆库存 Key。


总结

Redis 做预扣减,常见但不是银弹:

问题 后果 解法
缓存DB不一致 多卖或少卖 异常路径必须回滚 Redis 库存
少卖 库存留到结束没人买 秒杀订单超时缩到 2 分钟
Redis 宕机丢数据 库存状态对不上 调高 AOF 频率 + 主从哨兵
热 Key 单节点被打爆 静态数据放本地缓存 + 拆分库存 Key

说到底是三件事:一致性靠回滚兜底,高可用靠主从哨兵,高性能靠本地缓存 + 必要时拆 Key。 把这三件事想清楚,Redis 预扣减方案就能用。

相关推荐
一米阳光86615 小时前
软考(中级)软件设计师核心笔记(3)数据库系统——概念、数据库设计
数据库·笔记·职场发展·软考·软件设计师
奈斯先生Vector6 小时前
告别工具碎片化:基于 Nano Banana 全模态 AI 聚合架构搭建“文本-图像-视频”自动化协同生产线
运维·数据库·人工智能·架构·自动化·aigc·音视频
建筑工程企业管理系统7 小时前
erp工程项目管理系统落地价值:实现工程多项目成本精细化核算与管控
大数据·数据库·人工智能
AI大模型-小华8 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
foolishlee8 小时前
Neon wal日志处理流程2
数据库
2601_965798479 小时前
Is Hygia Good for Maid & Janitorial Sites? Technical Audit
服务器·网络·数据库
Cloud云卷云舒9 小时前
海山数据库(HaishanDB)面向工业云场景技术方案
数据库·haishandb·工业云·移动云海山数据库·天工云
逃逸线LOF9 小时前
Spring配置数据源{连接池}(Druid、c3p0)
java·数据库·spring
Valora10 小时前
简单学会redis
redis
严同学正在努力12 小时前
从备份到恢复:我用 30 分钟恢复了误删的核心业务表
android·java·数据库·ai