订单系统

关于本笔记

本文件介绍的是跟订单业务相关的知识

目录

核心问题

订单创建

订单创建看似只是一次写库, 本质是“用户意图 + 库存/价格校验 + 交易落库 + 后续动作触发”的组合动作。

  • 业务维度: 活动价格、优惠券、运费规则经常变化, 规则冲突会导致创建失败或金额错误。
  • 技术维度: 下单链路依赖库存、营销、用户、支付等模块, 任一环节慢或不可用都会放大失败率。
  • 数据维度: 幂等键缺失、请求重试、消息重复消费会导致重复订单。
  • 组织维度: 需求频繁迭代但缺少统一订单状态机, 造成“能下单但后续不可处理”的隐性问题。

订单延迟等待

订单延迟等待常见于“待支付超时关闭”“发货超时提醒”“自动确认收货”等场景。

  • 业务维度: 不同品类和渠道的超时时间不一致, 统一固定值会损失体验或资金周转效率。
  • 技术维度: 仅靠数据库轮询成本高, 高峰时容易出现延迟堆积。
  • 数据维度: 订单状态变化与延迟任务触发存在时间差, 容易出现任务误执行。
  • 稳定性维度: 服务重启、任务丢失、时钟漂移会导致应执行未执行或重复执行。

并发冲突

并发冲突的核心是“同一资源被同时修改”, 在订单场景中主要体现在库存、优惠券、用户余额、订单状态流转。

  • 热点资源: 爆品库存、秒杀券会形成热点写入, 导致超卖或锁等待。
  • 更新竞争: 多个线程同时修改同一订单状态, 可能出现状态回退或覆盖。
  • 分布式竞争: 多实例并发处理同一消息, 若缺少幂等控制会产生重复扣减。
  • 一致性边界: 强一致做得过重会拖垮吞吐, 过轻又会带来账实不符。

兜底策略

兜底策略用于处理“主流程理论上不该发生, 但线上一定会发生”的异常路径。

  • 异常来源: 第三方接口超时、消息丢失、局部网络抖动、代码回滚不一致。
  • 业务风险: 订单卡死、库存未回补、用户重复扣款、财务对账差异。
  • 运维风险: 人工补偿流程不可追踪、处理慢、误操作概率高。
  • 治理风险: 没有统一告警和补偿机制时, 小异常会累积成大故障。

解决思路

解决订单创建问题

先明确原因再选方案: 若主要是“单次失败”, 优先保证幂等与事务; 若主要是“链路复杂”, 需要拆分与异步化。

  • 普通方案: 单库事务 + 同步校验 + 本地幂等表。
    • 为什么可行: 实现简单, 对小流量和规则稳定场景足够。
    • 优点: 开发快、调试直观、排障路径短。
  • 优化方案: 预校验缓存化 + 关键动作异步化(如下单后推消息) + 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)继续细化为可直接落地的实现清单。