商城 SKU 与库存设计 超卖、锁库与退款

KLWIN建站团队 2026-11-08 约 5 分钟读完 约 1,547 字 338 次阅读

商城超卖往往不是代码写错,而是库存规则没定义清楚。本文拆解 SKU 拆分、可售/锁定/占用三个数、下单锁库时序、四种超卖场景与退款回滚,给出一套能对账的设计。

商城 SKU 与库存设计 超卖、锁库与退款
商城 SKU 与库存设计 超卖、锁库与退款

一个做食品的客户,活动当晚卖了 800 单,第二天发现其中 60 单没货。技术查了半天,结论是“并发扣减没加锁”。但真正的问题在更前面:他们把“仓库里有 1000 件”直接当成了“线上可卖 1000 件”,没有给已下单未发货、线下门店、预售留货留出位置。

库存不是一张表的一个数字,而是一组规则。规则没定清楚,加多少锁都会超卖。

先拆 SKU,再谈库存

SKU 的拆分标准是“用户是否需要单独选择”。颜色、规格、包装单位,只要会影响购买决策,就应该拆成独立 SKU;只在内部区分批次、供应商的,不要拆到前台,否则商品列表会变得无法维护。

拆完 SKU 后,每个 SKU 至少要有四个字段:可售库存、锁定库存、已售未发、安全库存。只用一个“库存”字段,后面所有场景都会打架。

三个数之间的关系

字段含义什么时候变
可售库存用户现在能下单的数量入库、锁定、释放、发货
锁定库存已下单未支付/未发货占用的数量下单锁定、支付确认、取消释放
已售未发已支付但仓库还没出的数量支付成功、发货完成

前台只展示可售库存。可售 = 实物库存 − 锁定 − 已售未发 − 安全库存。这个公式要写进系统,不要让运营手工改数字。

下单锁库的时序

推荐顺序:创建订单 → 校验可售 → 锁定库存 → 发起支付 → 支付成功转为已售未发 → 发货扣减实物库存。每一步都要有超时释放,未支付订单 15 到 30 分钟自动取消并释放锁定。

不要在支付成功后才锁库。那时用户已经付了钱,没货只能退款,体验最差。也不要在加入购物车时锁库,购物车不是承诺,会把库存占死。

四种超卖场景

  1. 并发下单:两个请求同时读到 1 件。用数据库行锁或原子扣减,不要“先查再改”。
  2. 多端同步:小程序、门店、平台共用库存,某端没同步。设一个库存中心,所有端走同一接口。
  3. 退款回滚:退款成功但库存没加回来,或者加回到错误的 SKU。退款单要记录原 SKU 和数量。
  4. 预售与现货混卖:预售占用了现货库存。预售单独建虚拟仓,不要和现货共用可售数。

退款与回滚的顺序

仅退款:确认未发货,库存从“已售未发”退回“可售”。退货退款:先收货质检,合格后回库,不合格走残次品仓,不能直接加回可售。部分退款:按明细回滚,不要按订单总额比例估算。

每一步都要留流水:谁、什么时候、从哪个仓、回滚多少。没有流水,月底对账一定对不上。

对账怎么做

每天跑一次:实物库存 = 可售 + 锁定 + 已售未发 + 残次 + 在途。差异超过阈值就告警。刚开始会有很多小差异,逐条查,通常能在两周内把规则跑顺。

不要把对账做成月底一次。月底发现差异,已经找不到是哪一单造成的了。

预售、组合装与赠品

预售商品单独建虚拟库存,不要占用现货。组合装要拆成子 SKU 扣减,任何一个子件不足,整单不可售。赠品也要占库存,否则活动结束才发现赠品发完了。

组合装的库存计算有两种方式:固定搭配按最小可组合数算,自由搭配按子件分别校验。不要用一个总数掩盖子件差异。

库存精度与盘点

线上库存不可能和仓库永远一致。设定一个可接受的差异率,比如 2%,超过就停售盘点。每天抽盘十个高频 SKU,比月底大盘更容易发现问题。

盘点期间要把可售库存临时置零,避免边盘边卖。盘点结束后按实际数调整,并记录原因:破损、错发、退货未入库。

库存准确性首先是运营问题,不是技术问题。先把入库、出库、退换货流程固定,再谈系统和锁。

相关阅读:CMS 数据库优化。

常见问题

库存放在数据库还是缓存?

以数据库为准,缓存只做展示。扣减必须落库,缓存可以异步刷新。用缓存做扣减,迟早会出现数据不一致。

秒杀要不要单独一套库存?

要。活动库存独立锁定,活动结束再回补。和日常库存混在一起,平时销售会被活动拖垮。

多门店怎么共享库存?

设总仓和门店仓,线上优先总仓,门店自提走门店仓。跨仓调拨要有在途状态,不要直接改两个仓的数字。

库存和支付、订单状态强相关,接入支付时建议一起看支付接入流程,把回调与对账一起设计。

K

KLWIN建站团队

KLWIN康林旺 内容团队,长期处理企业官网建设、CMS 模板开发与搜索优化的实际项目。文章里的数据和方法,来自交付过程中的记录,不引用未经核实的结论。

上一篇小程序订阅消息 三次触达的时机与文案下一篇 小程序首屏优化 分包、图片与请求的减法
RELATED

继续阅读

客服头像
正在连接...
👋
开始聊天前,请告诉我们您的称呼
客服 正在输入