秒杀场景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 预扣减方案就能用。

相关推荐
码不停蹄的玄黓1 小时前
生产可用的 Redis 分布式锁完整实现
数据库·redis·分布式
咸鱼翻身小阿橙1 小时前
文件读写 + Qt Model/View + 自定义分页+搜索过滤
java·数据库·qt
l1t1 小时前
DeepSeek总结的DuckDB-Iceberg 在 v1.5.3 中的新特性
数据库·duckdb
Database_Cool_1 小时前
数据仓库弹性扩缩容怎么实现?阿里云 AnalyticDB MySQL Serverless 弹性架构详解
数据库·人工智能·阿里云
abcy0712131 小时前
django聚合函数
数据库·sqlite
念越1 小时前
数据库系统概论第6版王珊版:第二章关系代数与第三章SQL期末重点整理
数据库·sql·性能优化
TDengine (老段)1 小时前
TDengine 数据保留与 TTL — 多级存储、过期删除与分层迁移
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
安当加密03011 小时前
等保2.0三级数据库加密:2026检查清单 + TDE部署实战(附脚本)
数据库·网络安全·数据安全·tde·等保2.0·数据库加密·tde透明加密
解决问题no解决代码问题1 小时前
TiDB 原理与节点宕机实战讲解
数据库·tidb