库存数据同步:从“天天对账”到“只管下单”的架构演进
做了十年电商系统,最怕的不是双十一流量洪峰,而是供应商那边说“没货了”——而你这边系统还显示库存充足。
这事儿我踩过不止一次。三年前一个代购客户,凌晨两点给我打电话,语气比白天冷静得多:“系统显示有货,我接了 50 单,供应商说早卖完了。现在怎么办?”电话那头安静了几秒,他补了一句:“五十单,每单赔 30%的违约金。”
那晚之后,我彻底改了对库存数据同步的理解。
库存不同步,到底谁在说谎?
很多团队刚做电商系统时,觉得库存同步不就是“供应商那边减 1,我这边减 1”吗?逻辑没错,但现实是——
供应商的库存更新有延迟。1688 的库存数据,大促期间延迟短则几分钟,长则半小时。你这边还在正常接单,那边仓库已经空了。更麻烦的是,供应商断货不会主动通知你。系统不主动查,你就永远不知道。
我见过最离谱的情况:一个 SKU 在 1688 显示库存 500+,实际只有 12 件。系统自动接单接了 300 多单,最后退了 200 多单。那周客服部门离职了两个人。
库存数据同步的核心问题不是技术,是信任——你无法信任一个延迟半小时的数据源。
从“拉”到“推”,再到“兜底”
早期我们做库存同步,就是定时拉取。每 5 分钟跑一次脚本,把供应商的库存拉回来更新本地。听起来简单,但问题在于:
- 5 分钟窗口期内,可能已经接了十几单
- 供应商接口不稳定,拉取失败时库存数据就卡在旧值上
- 大促期间接口响应变慢,5 分钟拉一次变成 10 分钟
后来改成供应商主动推送。但大部分供应商没有推送能力,尤其是 1688 这种平台型供应商。你没法要求人家给你开 Webhook。
最终我们做了三层兜底:
第一层:实时查询 + 本地缓存
下单时实时查供应商库存,同时本地缓存一份。缓存过期时间设得很短——30 秒。这样既减少对供应商接口的压力,又保证数据新鲜度。
第二层:库存水位预警
不等到库存为 0 再停售。设置一个安全水位线,比如库存低于 20 件时,系统自动标记为“低库存”,接单时弹窗提醒。这个水位线根据历史销量动态调整——卖得快的 SKU,水位线设得更高。
第三层:人工兜底流程
当系统检测到库存数据异常(比如供应商返回 0 但本地还有订单在途),自动生成异常工单,推送给运营人员。运营确认后,可以手动冻结该 SKU 的销售。
这套方案上线后,库存相关的客诉降了大概七成。当然,代价是代码复杂度翻了一倍。
一个真实的数据对比
同样处理 200 单:
- 纯定时拉取:每天对账需要 3 小时,出错率约 8%。客服要花大量时间解释“为什么显示有货却发不了”。
- 三层兜底方案:日常维护 40 分钟,出错率降到 1%以内。大部分异常在系统层面就被拦截了。
不是工具多厉害,是流程不一样了。
库存状态的”灰色地带”
很多系统只设计两种库存状态:有货/无货。但真实业务中,库存状态至少有四种:
- 确认有货:供应商明确回复有库存
- 待确认:库存数据延迟,需要人工核实
- 低库存预警:库存低于安全水位线
- 无货/断货:供应商确认无货
我见过一个团队,把“待确认”状态的商品直接标记为“有货”继续销售。结果可想而知。库存数据同步的难点,不在于同步本身,而在于如何定义“不确定”的状态。
架构演进:从单体到异步
早期我们用一个定时任务搞定所有库存同步。后来业务量大了,改成消息队列异步处理:
# 库存同步消息生产者
def publish_inventory_sync(sku_id):
message = {
'sku_id': sku_id,
'timestamp': int(time.time()),
'source': 'supplier_1688'
}
# 发送到消息队列
queue.send('inventory_sync', message)
消费者处理时,做了幂等设计——同一个 SKU 的同步请求,如果 5 秒内重复收到,直接丢弃:
# 库存同步消息消费者(带幂等)
def handle_inventory_sync(message):
sku_id = message['sku_id']
cache_key = f'inventory_sync:{sku_id}'
# 5 秒内重复消息直接丢弃
if redis.exists(cache_key):
return
redis.setex(cache_key, 5, 'processing')
# 从供应商接口获取最新库存
inventory = fetch_supplier_inventory(sku_id)
# 更新本地库存
update_local_inventory(sku_id, inventory)
这套架构跑了两年,双十一峰值时每天处理几十万条同步消息,没出过大问题。
库存数据同步的本质
说到底,库存数据同步不是技术问题,是业务问题。技术只是手段,核心在于:
- 接受不确定性:数据永远有延迟,设计时就要假设数据可能是错的
- 分层防御:不依赖单一路径,用多级兜底覆盖异常
- 状态清晰:不要只分“有/无”,给灰色地带一个明确的名字
后来那个凌晨打电话的客户,我们帮他重构了库存同步方案。现在他每天花在库存对账上的时间,从两小时缩到了十五分钟。上次见面,他说:“现在我只管下单,库存的事系统自己搞定。”
这句话,大概是做库存同步系统的人,最想听到的评价了。
关于作者
十年电商系统架构经验,从单体应用到分布式系统,踩过的坑比写过的代码多。目前在 taocarts 团队负责系统架构设计,专注解决跨境代购场景下的库存、物流、支付等复杂问题。欢迎交流,一起探讨技术背后的业务逻辑。
你在库存同步上踩过什么坑?欢迎留言分享,也许你的经历能帮到另一个正在熬夜对账的同行。
- 点赞
- 收藏
- 关注作者
评论(0)