ICP备案

备案站点的高并发库存扣减与超卖防护

作者:备案源头内容团队内容审核:备案源头内容团队更新于 2026年9月17日

显示有货却下不了单,和卖多了货,是同一个问题的两面

库存并发控制的失败通常以两种相反的形式出现:要么过度保守(库存实际还有,但并发扣减互相冲突,大量正常请求被误判为失败),要么过度乐观(多个请求都读到「还有货」,一起扣减成功,实际卖出的数量超过库存)。这两种问题的根源相同——都是没有正确处理并发读改写的时序问题

关键要点

  • 库存扣减必须是原子操作:读取当前库存和扣减库存之间不能有可被其他请求插入的空隙。
  • 乐观锁适合冲突不激烈的场景,悲观锁适合高频争抢的热点;选错会导致要么大量重试失败、要么吞吐骤降。
  • 缓存里的库存和数据库里的库存永远存在短暂不一致的窗口,设计时要承认这一点而不是假装它不存在。
  • 即使做对了并发控制,仍要有兜底对账,因为分布式系统里总有例外路径能绕过正常流程。

先分清两种失败模式

失败模式 表现 根因
超卖 卖出数量超过实际库存 读取与扣减之间存在竞态窗口
误判无货 库存明明够,大量请求却提示失败 悲观锁粒度过粗,或乐观锁重试次数不够

这两种问题经常同时出现在同一套系统的不同接口上:一个热点商品用了粗粒度的行锁,导致请求排队超时(误判无货);另一个冷门商品完全没做并发控制,逻辑上「先查后扣」两步之间被并发请求插了队(超卖)。

乐观锁:低冲突场景的首选

乐观锁的做法是在扣减时带上一个版本号或当前库存值作为条件,只有条件匹配时更新才生效,不匹配就重试。它不预先加锁,靠数据库的条件更新语义保证原子性。

优点是无冲突时几乎没有额外开销;缺点是高并发争抢同一行库存时,重试率会急剧上升,大量请求在「读取-失败-重试」之间空转,实际有效吞吐反而下降。适合库存基数大、单个商品被同时抢购的概率不高的常规场景。

悲观锁:高频热点的选择

悲观锁在读取库存时就加锁,其他请求必须等锁释放才能继续,从根本上消除了竞态窗口。代价是并发度直接被锁住的粒度限制——如果所有请求都在等同一把锁,热点商品的吞吐上限就是「单次扣减耗时的倒数」,远低于乐观锁在低冲突下的表现。

给秒杀这类极端热点场景用悲观锁时,通常还要配合库存分片:把一个商品的总库存拆成多个子库存桶,请求先哈希到某个桶再加锁,把原本串行的锁竞争拆成多路并行,显著提升吞吐上限。分片扣减完成后仍需要一次汇总一致性校验。

扣减与下单:原子性的边界该划在哪

一个常见错误是把「扣库存」和「创建订单」放在两次独立的操作里,中间没有事务包裹——扣减成功了,订单创建失败,库存却已经少了,形成幽灵扣减

正确做法是让扣减和下单在同一个事务边界内完成,或者用补偿机制保证最终一致:扣减库存的同时插入一条待确认的预扣记录,订单创建失败时自动释放预扣。长事务本身要克制,见 数据库连接池与连接数治理,跨服务场景下的对账补偿思路和第三方支付类似,见 第三方服务依赖治理

预扣记录也需要超时自动释放——用户下单到支付之间有等待窗口,长期占用未支付订单的库存会造成「假性缺货」,这类定时清理任务要做到幂等,见 定时任务运维:幂等、防重与补偿

缓存库存与数据库库存:接受不一致窗口的存在

高并发场景下直接打数据库扣库存,很容易把数据库压垮,见 数据库连接池与连接数治理。常见做法是把库存前置到缓存,扣减先在缓存里做,再异步同步到数据库。

这个方案的代价是缓存和数据库之间必然存在同步延迟,期间可能出现两边数字不一致。设计上要承认并容忍这个窗口,而不是试图追求瞬时强一致:

  • 缓存扣减本身要用原子操作(条件递减),避免缓存层自己产生竞态。
  • 数据库侧仍要有最终扣减校验,缓存扣减成功不代表数据库一定有货,缓存运维要点见 缓存与 Redis 运维
  • 缓存节点故障或数据丢失时,要有从数据库重建库存缓存的流程,并且重建期间的请求要能安全降级。

高并发下的限流与排队

热点商品的瞬时流量往往远超实际库存能支撑的处理能力,此时让所有请求都去抢锁是低效的——大部分请求注定失败,却仍然消耗了完整的处理链路资源。更好的做法是在入口层先做限流和排队:

分布式部署下的额外风险

多实例部署时,简单的「读取再更新」逻辑必然会遇到跨实例竞态。这不是加一把应用内的锁就能解决的——锁必须能跨实例生效,涉及的取舍和陷阱见 分布式锁与选主实践。多数场景下,数据库自身的原子更新语义(条件更新并检查受影响行数)比自己实现分布式锁更可靠、更简单,只有原子更新无法覆盖的复杂业务逻辑(如跨多个库存项的组合校验)才值得引入额外的锁机制。

兜底:对账和超卖后的补偿

无论并发控制做得多严密,都要假设极端情况下仍可能出现超卖(比如库存数据在迁移割接期间的短暂不一致,见 跨库迁移与割接实践)。因此需要:

  • 定期对账:统计订单总量与库存扣减总量是否匹配,发现差异自动告警。
  • 超卖补偿预案:提前想好是取消部分订单、补货、还是折价补偿,业务侧要在系统设计阶段就参与这个决策,而不是等真的超卖了才临时决定。
  • 把库存相关的异常路径都纳入监控,扣减失败率、预扣超时释放量都应该是常规观察的指标,见 可观测性建设备案网站监控告警体系

常见坑

  • 先查库存再扣减,两步之间没有原子保护:并发下必然超卖。
  • 热点商品用无锁乐观更新且不限重试次数:大量请求空转,看起来像系统故障。
  • 扣库存和建订单跨两个独立操作无补偿:出现幽灵扣减,库存越卖越少却没有对应订单。
  • 预扣记录没有超时释放:未支付订单长期占着库存,造成假性缺货。
  • 只做缓存扣减不做数据库校验:缓存数据丢失或不一致时直接超卖。

常见问题

乐观锁和悲观锁到底怎么选?

看冲突概率。日常商品的库存扣减冲突概率低,用乐观锁开销更小;秒杀这类瞬时高并发争抢同一件商品的场景,乐观锁会因为重试率过高导致有效吞吐下降,更适合悲观锁配合库存分片。同一个系统里,不同商品甚至可以采用不同策略。

已经用了分布式锁,为什么还会超卖?

常见原因是锁的范围没有覆盖完整的读改写周期,或者存在绕过锁的路径(比如后台管理系统直接操作库存表)。也可能是锁本身的实现存在时序漏洞,比如基于异步复制存储实现的锁在故障切换时出现短暂失效,具体机制见 分布式锁与选主实践

缓存库存和数据库库存不一致,应该以哪个为准?

数据库通常作为最终权威数据源,缓存是加速层。设计上应该允许缓存短暂领先或落后于数据库,但下单最终确认环节要有数据库层面的校验兜底,避免缓存数据错误直接导致超卖。

已经超卖了,运维和业务应该怎么应对?

先通过对账定位超卖的具体订单和数量,再按业务预案处理(补货、部分取消、协商补偿)。事后要复盘超卖发生的具体链路——是并发控制缺失、事务边界错误,还是缓存与数据库不一致——针对性修复,而不是简单加一层重试了事。

资料来源

主流数据库关于乐观并发控制与行锁机制的官方文档,以及电商类高并发库存扣减的公开架构实践资料。本文为通用运维说明,仅供参考,具体方案请结合实际业务规则与一致性要求设计。

相关阅读

网站访问日志留存与安全合规运维要点

为什么要留日志:这是法定要求 《网络安全法》第二十一条明确要求网络运营者"采取监测、记录网络运行状态、网络安全事件的技术措施,并按照规定留存相关的网络日志不少于六个月"。已完成备案、对外提供服务的网站属于网络运营者范畴,日志留存不是可选项,而是基础合规义务。 应留存哪些日志 | 日志类型 | 记录内容 | 主要用途 …

网站新增域名如何补充接入备案

企业在原有网站基础上新增域名,比如启用新的品牌域名或拼音域名指向同一网站时,不能直接绑定使用,而是需要在原备案基础上补充办理新增域名的接入手续。 新增域名前的准备工作 新增域名前,建议先确认该域名已经完成实名认证,可以通过 Whois查询 核对域名的注册信息和实名状态,避免因域名信息未实名导致接入申请被退回。同时确认…

备案信息年度核查该如何配合应对

部分省份的通信管理部门会对辖区内已备案网站开展年度或不定期核查,核查方式包括系统比对、电话回访、短信确认等,目的是确认备案信息与网站实际运营情况是否一致。 核查通常关注哪些内容 年度核查一般围绕主体信息、网站信息、接入信息三个维度展开,具体可以对照下表自查: | 核查维度 | 常见核查点 | | --- | --- …

备案号在网站上的规范展示与使用要求

网站完成备案只是第一步,备案号在页面上的展示方式同样需要长期维护,很多主体正是因为展示细节不规范,在日常巡查或年度核查中被要求整改。 展示位置与基本要求 通常做法是将备案号放置在网站首页底部,文字需清晰可辨、不被图片或广告遮挡,且格式应与下发的备案号文本保持一致,不能随意增减字符或调整顺序。是否需要加超链接指向查询入…

备案注销之后重新申请要注意什么

有些主体在此前因业务调整、接入商变更等原因注销了原有备案,之后又因新的业务需要重新申请备案。这种“二次备案”与首次备案在流程上大体相似,但有几个环节容易被忽略。 重新申请前的自查 重新申请前,建议先用 ICP备案查询 确认原备案是否确实已经完成注销,避免出现原备案未彻底清空、新申请与旧记录冲突的情况。同时检查计划使用…

备案信息变更有没有时效要求

备案不是办理完成后就一劳永逸的事项,主体信息、网站信息或联系方式一旦发生变化,通常需要在信息变化后的一定时间内完成变更提交,具体时限以属地管局要求为准。 哪些变化需要及时申报 常见需要变更的情形包括:主办单位名称或证件信息变化、网站负责人更换、联系电话或邮箱失效、网站域名调整、网站内容服务类型发生实质变化等。这类变更…

公司迁址之后备案地址信息如何更新

企业办公地址或注册地址发生变化后,备案信息中登记的地址项也需要相应更新,尤其是当迁址涉及跨区、跨市甚至跨省时,办理流程会比同城内迁址更复杂一些。 迁址后需要关注的信息 迁址后首先要确认工商登记信息是否已经完成同步变更,备案地址一般以工商登记的最新地址为准。可以先用 ICP备案查询 查看当前登记的主办单位地址,与最新的…

备案预留手机号邮箱变更该如何更新

备案信息中登记的手机号和邮箱,是管局与接入服务商联系网站负责人的主要渠道,用于发送核查通知、验证短信、审核结果等重要信息。这些联系方式一旦更换却未同步更新,容易导致关键通知被漏收。 常见需要更新的场景 负责人更换手机号或离职导致原号码停用; 企业邮箱系统迁移,原邮箱地址不再使用; 备案负责人变更,联系方式随之更换。 …

系统学习