KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA
08. 不能回滚的世界,怎样收拾部分成功? — keel 龙骨
一次变更包含两个步骤:
一次变更包含两个步骤:
- 把连接池从 20 改到 40;
- 向值班群发送变更通知。
第一步成功,第二步失败。配置服务和消息服务没有共享数据库事务,无法按下一个全局 rollback 按钮。
Saga 把长事务拆成本地事务
T1: 修改配置 C1: 恢复原配置
T2: 发送通知 C2: 通知通常不可撤回,只能发更正消息
Saga 记录每个本地事务是否完成,以及对应补偿是什么。失败时按业务规则执行补偿或交给人工处理。
补偿不是时间倒流
恢复 pool_limit=20 是一个新的写操作:
- 它可能因为资源版本变化而失败;
- 原值 20 可能已不再适合当前负载;
- 中间已经产生监控告警和审计记录;
- 下游系统可能已经读取过 40;
- 发出的消息无法从人的记忆中撤回。
因此补偿目标是恢复可接受的业务状态,而不是抹除历史。
先分类动作的可补偿性
| 类型 | 例子 | 恢复方式 |
|---|---|---|
| 可逆 | 修改可版本化配置 | 条件写回先前值 |
| 可抵消 | 创建工单、预留库存 | 关闭工单、释放预留 |
| 可更正 | 已发送通知 | 再发送更正,不伪装撤回 |
| 不可逆 | 外部付款完成、物理破坏 | 人工处置、保险/退款等领域流程 |
高不可逆动作应尽量后置,并在提交前提高审批与预检等级。
补偿顺序由依赖决定
通常按完成步骤的逆序补偿,但不是机械规则。若动作之间有业务依赖,补偿可能需要并行、延迟或人工批准。补偿本身也要幂等,因为恢复流程同样会重试。
flowchart LR
A[T1 配置成功] --> B[T2 通知失败]
B --> C{策略}
C -->|必须全成| D[C1 恢复配置]
C -->|允许降级| E[保留配置并创建人工通知任务]
D --> F[记录 compensated]
E --> G[记录 partially_succeeded]
Orchestration 和 Choreography
- 编排式 Saga:中央协调者明确调用下一步和补偿,流程易于追踪;
- 事件式 Saga:各服务对事件作出反应,耦合较低,但全局因果链更难观察。
Agent Harness 已经承担 Run 协调,教学项目采用编排式 Saga。生产项目可以使用工作流引擎持久化每一步。
检查理解
- 为什么“恢复原值”仍然可能失败?
- 已发送通知应该怎样补偿?
- 哪些动作应尽量安排在流程后部?