订单系统
订单系统
salt-fish关于本笔记
本文件介绍的是跟订单业务相关的知识
目录
核心问题
订单创建
订单创建看似只是一次写库, 本质是“用户意图 + 库存/价格校验 + 交易落库 + 后续动作触发”的组合动作。
- 业务维度: 活动价格、优惠券、运费规则经常变化, 规则冲突会导致创建失败或金额错误。
- 技术维度: 下单链路依赖库存、营销、用户、支付等模块, 任一环节慢或不可用都会放大失败率。
- 数据维度: 幂等键缺失、请求重试、消息重复消费会导致重复订单。
- 组织维度: 需求频繁迭代但缺少统一订单状态机, 造成“能下单但后续不可处理”的隐性问题。
订单延迟等待
订单延迟等待常见于“待支付超时关闭”“发货超时提醒”“自动确认收货”等场景。
- 业务维度: 不同品类和渠道的超时时间不一致, 统一固定值会损失体验或资金周转效率。
- 技术维度: 仅靠数据库轮询成本高, 高峰时容易出现延迟堆积。
- 数据维度: 订单状态变化与延迟任务触发存在时间差, 容易出现任务误执行。
- 稳定性维度: 服务重启、任务丢失、时钟漂移会导致应执行未执行或重复执行。
并发冲突
并发冲突的核心是“同一资源被同时修改”, 在订单场景中主要体现在库存、优惠券、用户余额、订单状态流转。
- 热点资源: 爆品库存、秒杀券会形成热点写入, 导致超卖或锁等待。
- 更新竞争: 多个线程同时修改同一订单状态, 可能出现状态回退或覆盖。
- 分布式竞争: 多实例并发处理同一消息, 若缺少幂等控制会产生重复扣减。
- 一致性边界: 强一致做得过重会拖垮吞吐, 过轻又会带来账实不符。
兜底策略
兜底策略用于处理“主流程理论上不该发生, 但线上一定会发生”的异常路径。
- 异常来源: 第三方接口超时、消息丢失、局部网络抖动、代码回滚不一致。
- 业务风险: 订单卡死、库存未回补、用户重复扣款、财务对账差异。
- 运维风险: 人工补偿流程不可追踪、处理慢、误操作概率高。
- 治理风险: 没有统一告警和补偿机制时, 小异常会累积成大故障。
解决思路
解决订单创建问题
先明确原因再选方案: 若主要是“单次失败”, 优先保证幂等与事务; 若主要是“链路复杂”, 需要拆分与异步化。
- 普通方案: 单库事务 + 同步校验 + 本地幂等表。
- 为什么可行: 实现简单, 对小流量和规则稳定场景足够。
- 优点: 开发快、调试直观、排障路径短。
- 优化方案: 预校验缓存化 + 关键动作异步化(如下单后推消息) + Outbox 事件表。
- 为什么可行: 将“必须成功”与“可延后”动作分离, 降低主链路耗时。
- 优点: 吞吐更高, 峰值更稳, 故障影响面更小。
- 最优解: 统一订单领域模型 + 状态机 + 事件驱动(Saga/编排)。
- 为什么可行: 用状态迁移约束业务合法性, 用事件保障跨服务协同。
- 优点: 可扩展、可审计、跨团队协作成本低。
解决订单延迟等待问题
先区分“时间触发任务”与“状态驱动任务”: 延迟本身不是目标, 正确执行才是目标。
- 普通方案: 数据库定时扫描 + 条件更新。
- 为什么可行: 不引入中间件, 成本低。
- 优点: 易上线, 适合低并发。
- 优化方案: 简单的延迟消息实现(Redis ZSet/DelayQueue + Task/ScheduledThreadPoolExecutor) + 执行前状态二次校验。
- 为什么可行: 通过消息触发代替全表扫描, 再用状态校验防误关单。
- 优点: 资源开销更低, 任务精度更高。
- 最优解: 专用延迟调度平台(Kafka 等消息中间件/时间轮) + 幂等消费 + 死信回补。
- 为什么可行: 将调度可靠性与业务逻辑解耦, 支持海量任务。
- 优点: 高可用、可观测、可回放补偿。
解决订单并发冲突问题
并发治理要同时考虑“正确性、性能、可恢复性”, 不是只上锁。
- 普通方案: 乐观锁(version) + 条件更新(where status=?)。
- 为什么可行: 冲突由数据库原子性兜底, 失败可重试。
- 优点: 无需重锁, 吞吐相对高。
- 优化方案: 分段锁/热点隔离 + 请求去重 + 限流降级。
- 为什么可行: 将冲突从全局缩到局部, 把高峰流量削平。
- 优点: 降低锁竞争, 稳定性明显提升。
- 最优解: 一致性协议化(库存预占 + 订单确认/释放) + 幂等令牌 + 事件最终一致。
- 为什么可行: 把“抢同一资源”改成“有协议的状态转换”, 冲突可控。
- 优点: 兼顾高并发与一致性, 适合大促和多服务协作。
实现订单兜底策略
兜底不是补丁, 应该是主流程的并行设计。
- 普通方案: 失败重试 + 人工补单/回滚。
- 为什么可行: 快速建立最小闭环。
- 优点: 实施门槛低, 可立刻降低损失。
- 优化方案: 自动补偿任务 + 告警分级 + 可追踪工单。
- 为什么可行: 将“发现-定位-处理”流程标准化。
- 优点: 降低人工依赖, 响应更快。
- 最优解: 全链路可观测(指标/日志/Trace) + 自愈编排 + 对账驱动补偿。
- 为什么可行: 通过统一证据链定位问题, 通过对账闭环修复结果。
- 优点: 故障可预警、可回放、可验证。
方案实现
订单创建的具体多实现
业务展开: 订单创建通常包含“风控校验 -> 价格与优惠计算 -> 库存预留 -> 订单落库 -> 触发支付/履约”。
| 架构形态 | 分层方案 | 适用业务 | 核心技术栈 | 关键实现点 | 优点 | 缺点/风险 |
|---|---|---|---|---|---|---|
| 普通单体 SpringBoot | 普通 | 日单量低、规则简单 | SpringBoot + MySQL + JPA/MyBatis | @Transactional + 唯一索引(user_id,biz_no) + 参数校验 |
上线快、排障直观 | 高峰易慢、扩展性弱 |
| 普通单体 SpringBoot | 优化 | 日单量中等、活动频繁 | SpringBoot + Redis + MySQL(Outbox) + MQ(RabbitMQ/Kafka) | 主链路只做核心落单, Outbox 异步发事件 | 降低接口RT、抗峰值更好 | 需要处理消息重复与顺序 |
| 普通单体 SpringBoot | 最优 | 需要逐步向分布式演进 | Spring Statemachine/自研状态机 + DDD 分层 + Outbox | 订单状态机约束流转, 领域事件驱动后续动作 | 业务边界清晰、迁移成本低 | 设计复杂度上升 |
| 微服务大项目 | 普通 | 拆分初期、团队少 | SpringCloud/Boot + OpenFeign + MySQL | 订单服务同步调用库存/营销后创建订单 | 业务路径容易理解 | 强依赖下游可用性 |
| 微服务大项目 | 优化 | 峰值流量明显、链路长 | API Gateway + Redis + Kafka/RocketMQ + 服务编排 | 核心同步、非核心异步; 下单编排服务收敛流程 | 稳定性提升、便于扩容 | 链路追踪和治理成本上升 |
| 微服务大项目 | 最优 | 多团队协作、大促常态 | Saga(Seata/自研) + 幂等网关 + 事件版本化 | 通过 Saga 保证跨服务一致性, 事件驱动库存/营销/履约 | 扩展性最强、容错高 | 开发门槛高, 需完善治理平台 |
为什么这些实现可以: 订单创建是“强事务核心 + 弱事务扩展”组合, 分层后能把一致性压力集中在核心链路, 同时保证吞吐。
订单延迟等待的具体多实现
业务展开: 核心场景包括“超时未支付关单、超时未发货提醒、超时自动收货、售后超时自动处理”。
| 架构形态 | 分层方案 | 适用业务 | 核心技术栈 | 关键实现点 | 优点 | 缺点/风险 |
|---|---|---|---|---|---|---|
| 普通单体 SpringBoot | 普通 | 任务量小、可接受秒级误差 | @Scheduled + MySQL |
定时扫描 status=UNPAID and expire_time < now() 后条件更新 |
无额外中间件、成本低 | 扫描压力大、精度一般 |
| 普通单体 SpringBoot | 优化 | 任务量中等、要求更准时 | Redis ZSet/DelayQueue + Spring Task | 到期弹出后做“状态二次校验”再执行业务 | 减少全表扫描、延迟更可控 | Redis 内存占用与丢失风险需兜底 |
| 普通单体 SpringBoot | 最优 | 任务量大、失败需可追踪 | RabbitMQ TTL+DLX 或 RocketMQ 延迟消息 + 幂等表 | 消费端幂等, 失败进入死信并自动重放 | 高可靠、可回补 | 运维复杂度提升 |
| 微服务大项目 | 普通 | 拆分早期 | 各服务本地定时任务 | 每个服务自扫自处理 | 启动快、改造少 | 规则分散、重复建设 |
| 微服务大项目 | 优化 | 多业务线共享延迟能力 | 统一调度服务 + MQ + 配置中心 | 到期事件平台统一发出, 业务服务订阅处理 | 统一治理、降低重复开发 | 平台服务成为关键依赖 |
| 微服务大项目 | 最优 | 海量任务、审计严格 | 时间轮/分片调度平台 + Kafka/RocketMQ + 可观测平台 | 分片调度、重试、死信、回溯、审计一体化 | 可扩展性强、可观测 | 建设周期长、投入大 |
为什么这些实现可以: 延迟任务本质是“时间索引 + 状态校验 + 幂等执行”, 只要这三点闭环, 方案就能稳定落地。
订单并发冲突的具体多实现
业务展开: 并发冲突主要集中在“库存扣减、优惠券核销、订单状态变更、支付回调重复通知”。
| 架构形态 | 分层方案 | 适用业务 | 核心技术栈 | 关键实现点 | 优点 | 缺点/风险 |
|---|---|---|---|---|---|---|
| 普通单体 SpringBoot | 普通 | 常规并发 | MySQL 乐观锁 + 条件更新 | where id=? and status=? and version=? 更新失败重试 |
实现简单、正确性强 | 高冲突时重试多 |
| 普通单体 SpringBoot | 优化 | 有热点商品 | Redis Lua 原子扣减 + 本地队列/MQ 回写 | 热点先在 Redis 扣减, 再异步落库对账 | 抗热点能力强 | 需要处理缓存与数据库差异 |
| 普通单体 SpringBoot | 最优 | 促销高峰 + 支付回调频繁 | 幂等 Token + 本地事务消息 + 对账任务 | 下单防重、消费防重、异常自动校正 | 一致性和性能平衡较好 | 实现与测试复杂 |
| 微服务大项目 | 普通 | 分布式初期 | Redisson/ZooKeeper 锁 + 数据库事务 | 关键流程加分布式锁串行化 | 改造快、立刻止血 | 吞吐受锁限制 |
| 微服务大项目 | 优化 | 热点集中且流量大 | 分区分桶 + Kafka 分区有序消费 + 限流 | 将热点键路由到固定分区, 降低全局竞争 | 性能提升明显 | 分区倾斜需治理 |
| 微服务大项目 | 最优 | 大促常态、强一致要求高 | 库存预占协议 + Saga + 最终一致事件 | 预占->确认/释放, 超时自动回收, 全链路幂等 | 正确性高且可扩展 | 架构复杂、治理要求高 |
为什么这些实现可以: 并发冲突无法消灭, 只能被“局部化、协议化、幂等化”, 这样才能在高并发下保持可控。
订单兜底策略的具体多实现
业务展开: 兜底策略覆盖“消息丢失补偿、支付成功但订单未更新、库存未回补、跨系统数据不一致”。
| 架构形态 | 分层方案 | 适用业务 | 核心技术栈 | 关键实现点 | 优点 | 缺点/风险 |
|---|---|---|---|---|---|---|
| 普通单体 SpringBoot | 普通 | 异常量低 | MySQL 失败表 + 人工后台 | 异常入库并提供人工处理入口 | 快速可用 | 严重依赖人工 |
| 普通单体 SpringBoot | 优化 | 异常量增长 | 定时补偿任务 + 告警(邮件/钉钉/企业微信) | 指数退避重试, 超阈值升级告警 | 响应更快、成本更低 | 规则维护成本增加 |
| 普通单体 SpringBoot | 最优 | 需要可观测与审计 | 失败中心 + Prometheus/Grafana + Trace | 失败分类、自动重试、可视化工单闭环 | 可追踪、可度量、可持续优化 | 建设量较大 |
| 微服务大项目 | 普通 | 多服务刚拆分 | 各服务本地重试 | 各自处理自身异常 | 上线快 | 缺乏全局一致策略 |
| 微服务大项目 | 优化 | 有跨服务故障 | OpenTelemetry + 统一告警 + 补偿编排服务 | 统一异常入口, 通过编排执行跨服务补偿 | 处理效率高、定位快 | 依赖基础平台成熟度 |
| 微服务大项目 | 最优 | 财务审计严格、体量大 | 对账平台(订单/库存/支付) + 自动修复引擎 + 审计日志 | 日清日结对账, 差异自动修复, 全流程留痕 | 结果可验证、风险最低 | 投入最大, 需长期运营 |
为什么这些实现可以: 兜底能力的核心是“发现异常 -> 定位原因 -> 自动/人工补偿 -> 验证结果”, 技术栈只是实现这条闭环的手段。
总结
订单处理没有放之四海而皆准的“唯一正确方案”, 要按业务规模与复杂度分层设计:
- 小体量系统先做对: 先把幂等、状态机、异常闭环补齐。
- 中体量系统做稳: 把异步化、延迟调度、并发治理做成标准组件。
- 大体量系统做强: 以领域模型和事件驱动为核心, 通过平台化能力保障高可用与可演进。
本版本为初始填充稿, 后续可结合你当前业务数据(峰值QPS、订单量、库存模型、支付链路SLA)继续细化为可直接落地的实现清单。

