同城电商系统:库存变更怎么同步到订单

同城电商系统 库存变更若不同步到订单占用层,会出现「后台显示有货、实际已被未支付单占满」。宜库存 = 物理量 - 占用量;占用在下单创建,支付成功转实扣,超时释放。

模型

text 复制代码
sku_stock: on_hand
sku_hold: sum(active holds)
available = on_hand - sku_hold

下单预占

python 复制代码
def create_order(lines):
    with stock.lock(sku_ids(lines)):
        for line in lines:
            if available(line.sku_id) < line.qty:
                raise OutOfStock(line.sku_id)
            hold_repo.insert(line.sku_id, line.qty, order_id, ttl=900)
    return order_repo.insert(...)

支付成功

python 复制代码
def on_paid(order_id):
    for h in hold_repo.by_order(order_id):
        stock_repo.decrement(h.sku_id, h.qty)
        hold_repo.release(h.id)

改库存

python 复制代码
def adjust_on_hand(sku_id, delta):
    stock_repo.adjust(sku_id, delta)
    # 不回写已存在 hold;available 自动重算

验收

未支付单占满时,新单拒绝;改 on_hand 不影响已支付单 line snapshot;超时 hold 释放。

光合同城边界

光合同城同城电商成品含库存占用逻辑;可按业务定制;商务规则由客户确定。

小结

同城电商系统库存变更通过占用层同步到可售量,订单行 snapshot 保历史一致。

超时释放 hold

python 复制代码
def release_expired_holds():
    for h in hold_repo.expired(before=now()-900):
        hold_repo.release(h.id)
        # on_hand 不变,available 自动回升

定时任务每分钟跑;监控 expired 释放失败数。

并发扣减

行锁 SELECT ... FOR UPDATE 或 Redis 预减 + 异步落库;切忌读 available 后无锁写 hold。

与订单取消

python 复制代码
def cancel_unpaid(order_id):
    order_repo.cancel(order_id)
    hold_repo.release_by_order(order_id)

压测指标

单 SKU 1000 QPS 下单,观察 hold 表行数与 available;不应出现 available 长期为负。

光合同城

同城电商成品含占用逻辑;可按促销规则定制;商务规则由客户确定。

小结

同城电商系统库存变更同步到占用层,配合 snapshot 与超时释放,是可售量与历史单一致的双保险。

秒杀与热点 SKU

热点 SKU 可 Redis 预减 + 异步写 hold;MySQL 为最终真相,定时对账 Redis 与 hold 表。

python 复制代码
def flash_hold(sku_id, qty):
    if not redis_decr(sku_id, qty):
        raise OutOfStock()
    queue.publish({"sku_id": sku_id, "qty": qty, "order_id": ...})

订单行 snapshot 字段

python 复制代码
order_line = {
    "sku_id": sku.id,
    "title": sku.title,
    "unit_price": sku.price,
    "qty": line.qty,
    "stock_version": sku.version,
}

改库存不 retroactive 改 line。

监控

hold_expired_total、oversell_alert、redis_db_drift 分指标告警。

小结补述

同城电商系统库存变更 → 占用 → snapshot 三层分工,促销高峰靠预减与异步,平时靠行锁即可。

上线前压测清单

单 SKU 500 QPS 预减 5 分钟;MySQL hold 与 Redis 偏差 <0.1%;超时 release 任务延迟 <60s。三项通过后,再对外开大促入口,避免「活动一开就超卖」集中暴露架构短板。

促销前清过期占用

同城电商系统大促前若不清过期占用,会出现后台显示还有货、实际已被未支付单占满。下单预占、支付成功实扣、超时释放,三层缺一层就会超卖或误拒单。改库存只动物理量,不回写已存在占用;可售量等于物理量减占用量,自动重算。

热点商品可用 Redis 预减加异步写占用,数据库为最终真相,定时对比 Redis 与占用表偏差。订单行写入下单时商品标题、单价、数量快照,改库存不 retroactive 改历史行。压测单 SKU 高并发下单,观察占用表行数与可售量,不应长期为负。三项压测通过再开大促入口。

秒杀场景 Redis 预减失败应快速拒绝,异步 worker 写占用失败进死信队列补写。订单行带库存版本字段,改库存不 retroactive 改历史行,纠纷时导出订单行是最硬证据。

超卖与拒单都源于占用层缺失

未支付单占满库存时新单应拒绝;改物理库存不影响已支付单快照。超时释放任务每分钟跑,监控 expired 释放失败数。热点 SKU 可 Redis 预减加异步写占用,数据库为最终真相,大促后全量对账一次。订单行写入下单时标题、单价、数量快照,改库存不 retroactive 改历史行;纠纷时导出订单行是最硬证据,商家履约也以快照为准。压测单 SKU 高并发下单,观察占用表与可售量,不应长期为负。Worker 写占用失败进死信队列补写,Redis 预减与 MySQL 最终一致,对账以数据库为准。大促后宜全量对账一次。交付宜附压测报告与死信补写流程说明。

相关推荐
.Bryce.1 分钟前
你了解 Blackboard(黑板系统)吗?听说过基于黑板系统实现的智能体吗?
java·网络·gpt·php·agent·codex·黑板系统
银河技术15 分钟前
从脚本到 Operator:用 Go 构建可靠的微服务自动扩缩容控制器
开发语言·微服务·golang
GIS数据转换器2 小时前
地下空间综合管廊运营管理平台
大数据·开发语言·人工智能·经验分享·perl
猿究院_夏燊7 小时前
Spring Bean 生命周期
java·后端·spring
Wang's Blog7 小时前
Java 项目实战: 交友项目:登录链路回顾与今日任务地图
java·开发语言·状态模式·交友
信誓旦旦的程序猿8 小时前
【Python量化实战宝典 #08】可转债与债券接口手册:转股价·溢价率·纯债价值(Python 可跑)
java·python·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口
砚底藏山河8 小时前
python量化:行情数据回溯
java·开发语言·python·金融·maven
今年下半年8 小时前
AI智能体项目实战记录(02):初始化 Python 项目
开发语言·人工智能·python·fastapi
Jlzn88888 小时前
华东电芯分选通道数怎么配才不堵线
java·人工智能·架构·自动化·制造
Williamtym8 小时前
PickGo Lab实践:用浏览器、Python和MCP串起机器人搬运仿真
开发语言·python·机器人