1. 课程导入与全景认知

在交易、电商、票务、支付等系统中,订单是最核心的业务实体之一。用户下单、支付、发货、收货、退款、取消,每一步都会改变订单的状态。如果这些状态变化只靠零散的 if-else 判断来维护,系统很快就会陷入“状态混乱、事件丢失、重复处理、难以追溯”的困境。本课程要讲的订单新增撤销成交事件状态机,正是为了解决这类问题而设计的一套建模与实现方法。

先明确三个关键词的含义。新增指订单被创建并进入初始状态;撤销指订单在特定条件下被取消或回退;成交指订单完成支付或确认,进入终态。三者不是孤立的动作,而是由事件驱动的状态迁移过程。所谓事件驱动,是指系统不直接修改订单状态,而是接收一个事件(如“支付成功”“用户取消”“超时未支付”),由状态机根据当前状态和事件类型决定是否迁移、迁移到哪个状态、以及触发哪些副作用。

为什么需要状态机而不是普通字段更新

假设订单表只有一个 status 字段,代码里到处写 UPDATE orders SET status = 2 WHERE id = ?。这种写法有三个隐患:第一,非法迁移无法拦截,比如已成交订单被再次撤销;第二,并发场景下状态可能被覆盖,两个请求同时读到“待支付”并各自写入不同结果;第三,状态变化没有统一入口,审计和补偿无从下手。状态机把“允许哪些迁移”显式定义出来,把“事件→状态”的映射集中管理,从而让订单生命周期变得可验证、可测试、可追溯。

下图展示了本课程要建立的全景认知:左侧是订单的核心状态集合,中间是驱动迁移的事件,右侧是状态机对外提供的处理能力。图中只保留主干关系,帮助你在进入细节之前先建立整体骨架。

订单新增 · 撤销 · 成交:事件驱动状态机全景 订单状态 待支付(初始) 已支付 已成交(终态) 已撤销(终态) 超时关闭(终态) 驱动事件 OrderCreated PaymentSucceeded CancelRequested PaymentTimeout RefundCompleted 状态机能力 迁移合法性校验 拒绝非法事件 幂等与并发控制 版本号 / 唯一键 副作用编排 库存 / 账务 / 通知 状态变更留痕 事件日志可回放 状态只由事件驱动迁移;终态不可再迁移;每次迁移必须可校验、可留痕、可重放

事件驱动架构概览

在事件驱动架构中,订单服务不再被上游直接“改状态”,而是接收事件并作出反应。典型链路是:用户操作或定时任务产生事件 → 事件进入消息通道(如 Kafka、RocketMQ 或本地事务表)→ 订单状态机消费事件 → 校验迁移合法性 → 写入新状态并记录事件日志 → 发布领域事件通知下游(库存、账务、通知)。这条链路的关键在于状态机是唯一的状态写入口,任何绕过它的更新都应被视为缺陷。

需要区分两类事件:命令事件表达“请求做什么”,如 CancelRequested,可能被拒绝;事实事件表达“已经发生了什么”,如 PaymentSucceeded,通常不可否认。状态机对命令事件做校验,对事实事件做响应。理解这一点,才能在设计迁移表时正确决定哪些事件可以触发拒绝分支。

本课程的学习路径与实战目标

课程将沿着“建模—实现—验证—排障”的路径推进。前期先定义状态集合、事件集合与迁移表,明确初始态、终态和非法迁移;中期用代码实现状态机的核心方法,包括迁移校验、幂等处理、并发控制和事件日志;后期通过测试用例覆盖正常路径与异常路径,并用日志和状态快照定位问题。实战目标不是背概念,而是能独立完成一个可运行的订单状态机模块,并能解释每一次状态变化的原因。

为了让你对“迁移表”这一核心交付物有直观认识,下面给出一个示例片段。它属于教学示例,字段和取值可根据实际业务调整:

当前状态      事件                目标状态      说明
待支付        OrderCreated        待支付        创建即初始态
待支付        PaymentSucceeded    已支付        支付成功
待支付        CancelRequested     已撤销        用户主动取消
待支付        PaymentTimeout      超时关闭      定时任务触发
已支付        RefundCompleted     已撤销        退款完成回退
已支付        CancelRequested     已支付        拒绝,需先退款
已成交        *                   已成交        终态,拒绝一切迁移
已撤销        *                   已撤销        终态,拒绝一切迁移

这张表就是后续实现的“契约”。代码中的迁移判断、测试中的断言、排障时的对照,都应回到这张表。课程中会反复强调:先定表,再写码;表不变,码不乱。当你能够独立维护这样一张迁移表,并让系统严格按照它运行时,订单状态机才真正发挥了价值。