青蓝模式履约引擎:生鲜与饮用水行业订单-库存-配送调度一体化设计
摘要:本地生活履约的痛点,往往不是"某个环节慢",而是订单、库存、配送三张皮。本文深入讲解一体化履约引擎的设计:统一状态机、库存预占与回补、实时调度如何串联,并给出可用的工程实现思路。
写在前面
我是贺小晴,微三云一线架构师。
上一篇讲了青蓝模式的行业 SaaS 整体架构,这一篇往深处走一层:履约引擎本身怎么设计。见过太多系统,订单、库存、配送各管各的,结果"显示有货却送不出""送了才发现库存没扣"。问题就出在三者没被一个引擎统一驱动。下面讲怎么解。
一、核心思想:一个状态机驱动全链路
履约定义成一条统一状态机,订单的每一次状态变化,都驱动库存和配送联动:
待支付 → 已支付(预占库存) → 已出库(扣减库存) → 配送中 → 已签收(释放预占/结算)
│ │
支付超时 异常回退
└─── 释放预占库存 ───────────┘
关键点:库存的"预占"和"扣减"是两个动作,分别对应"已支付"和"已出库",不能用一次扣减糊弄。
二、库存:预占 + 回补,杜绝超卖
- 预占(reserved) :支付成功后即占用,防止并发超卖;
- 扣减(committed) :出库时由预占转实扣;
- 回补(rollback) :支付超时或取消,释放预占。
-- 预占:原子更新 available = available - n, reserved = reserved + n
UPDATE stock SET available = available - ?, reserved = reserved + ?
WHERE sku = ? AND available >= ?;
-- 影响行数为 0 即库存不足,直接拒单
这行 SQL 的原子性是防超卖的底线,曾因有人改成先查后减,出现过超卖事故。
三、配送:从"被动接单"到"主动调度"
订单进入"已支付"后,不直接派给某个送水工,而是进入调度池,由调度服务按规则聚单:
| 策略 | 说明 |
|---|---|
| 地理聚类 | 同小区订单并单送 |
| 时间窗 | 按客户期望时段排序 |
| 载重约束 | 单车容量上限 |
| 优先级 | 临期/加急单前置 |
调度结果写回订单的"配送任务",送水工 App 拉取执行。
四、一体化带来的工程收益
- 一致性:状态机保证库存与配送不脱节;
- 可观测:每个订单能从一棵树上追溯全链路;
- 可演进:调度策略独立迭代,不影响下单与库存。
五、踩坑
- 预占不释放:取消流程漏了回补,库存"假空",后加全链路超时兜底释放。
- 调度同步阻塞下单:高峰期卡顿,改异步队列解耦。
- 状态机缺幂等:重复回调导致重复扣减,加状态迁移幂等校验。
六、引擎 checklist
| 项 | 是否 | 说明 |
|---|---|---|
| 统一履约状态机 | □ | 驱动全链路 |
| 预占 + 扣减分离 | □ | 防超卖 |
| 库存操作原子化 | □ | SQL 原子更新 |
| 调度异步解耦 | □ | 保下单 |
| 状态迁移幂等 | □ | 防重复 |
七、状态机的幂等实现
状态迁移怕重复回调(支付平台多次通知)。给每个迁移加了目标态幂等:
func Transit(orderID, from, to string) error {
res := db.Exec(`UPDATE orders SET status=?
WHERE id=? AND status=?`, to, orderID, from)
if res.RowsAffected == 0 {
return ErrAlreadyTransited // 已是 to,直接成功
}
return nil
}
WHERE status=? 保证只有当前确为 from 才迁移,重复通知落空,天然幂等。
八、实时跟踪与可追溯
每个订单维护一棵履约树:根节点是订单,子节点是库存动作、调度任务、签收记录,全部带 traceId 串联。
| 节点 | 记录 | 用途 |
|---|---|---|
| 库存 | 预占/扣减 | 查超卖 |
| 调度 | 聚单/路线 | 查延迟 |
| 签收 | 时间/人 | 查纠纷 |
客服查这单为什么没送,一眼能看见卡在哪一环——是库存没扣、调度没聚、还是送水工没签收。可观测性把扯皮变成了定位。
九、边界情况与兜底
真实履约里,边界情况比主流程还多:
- 出库一半库存损毁:已预占部分转扣减,剩余回补,订单拆单或取消;
- 送水工失联:调度池自动回收任务,重新聚单派发;
- 客户拒收:状态机回退到已出库,库存回补,触发二次调度。
给每个异常都配了补偿动作,写进状态机而不是散落在业务 if-else 里。这样新增异常类型时,只扩展状态迁移表,不动主链路。可演进性来自"异常也是一等公民",而不是事后打补丁。
结语
履约引擎的难度,不在单点技术,而在"让三个本该独立的系统,像一个人一样协同"。统一状态机 + 预占回补 + 异步调度,是在生鲜与饮用水场景验证过的组合。行业 SaaS 真正值钱的地方,就藏在这条一体化链路里。
作者:贺小晴