Documentation
¶
Overview ¶
Package saga 提供跨服务 Saga 编排:按顺序执行一组"正向操作",任一步失败时 逆序执行已成功步骤的"补偿操作",达成最终一致。
与 pkg/txn 的区别(互补):
- txn 是同进程 2PC:参与者在内存里 Prepare(暂存不提交),失败真回滚; 要求所有参与者能被同步调用且支持"预留不提交"。
- saga 是跨服务最终一致:每步正向操作当场生效(如 RPC 落库,无法预留), 失败时靠"补偿"(业务定义的反向操作,是一笔新操作而非回滚)把已做的抵消掉。 用于参与者分散在多个服务、无法 2PC 的场景。
执行语义(Execute):
- 按注册顺序执行每个 Step.Action;
- 全部成功 → StatusCommitted;
- 第 k 步失败 → 逆序补偿第 k-1…1 步(跳过无补偿的步骤): 补偿全成功 → StatusCompensated(数据一致,返回原始失败原因); 某步补偿失败 → StatusCompensationFailed(数据不一致,须告警 + 人工介入)。
关键约束(MVP,纯内存):
- 补偿必须幂等:补偿会因重试重复执行。责任在调用方——推荐正/反向都用 幂等键实现(如 wallet.ApplyTx(txID) / wallet.ApplyTx(refundID));
- 不持久化:协调器进程崩溃则进行中的 saga 丢失、无法恢复。仅适合"单进程内 编排多个 RPC、进程存活期间完成"的流程,不是可靠分布式事务;
- 无隔离性:执行中的中间态(钱扣了货没发)对其他请求可见,业务需容忍;
- 当步 Action 失败不补偿当步——只补偿已成功的前序步骤,当步的部分副作用 须靠 Action 自身幂等 / 其补偿设计覆盖。
Action/Compensate 中的 panic 被 pkg/safe 转为 error(走正常失败/补偿流程)。 补偿阶段使用 context.WithoutCancel:原请求 ctx 取消不应中断补偿(副作用须补完)。
崩溃恢复:本包不持久化。生产环境依赖「可重投的触发源」(如 MQ at-least-once) 实现恢复——协调器崩溃后消息重投、saga 从头重跑,靠「幂等的 Action/Compensate」 保证不产生重复副作用。 前提:幂等键必须来自触发消息、跨重投稳定(如 msg.OrderID),不可用 idgen/uuid 现场生成——现场生成会让每次重投的键都不同,幂等失效、重复扣款。 仅当触发源不可重投(如不会重试的同步请求)时,才需要外部持久化 saga 状态并在 重启时恢复进度——那种场景本包不覆盖。
零值不可用,用 New 构造。单个 Saga 的 Execute 非并发安全(一次编排一个流程); 不同 Saga 实例相互独立。
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Option ¶
type Option func(*config)
Option 配置 Saga。
func WithCompensationRetry ¶
WithCompensationRetry 设置补偿失败的重试次数与基础退避间隔(指数退避)。 retries 为额外重试次数(0=只试一次),delay 为首次退避(第 n 次退避 = delay<<n)。 补偿是挽救不一致的最后手段,适度重试能显著降低 StatusCompensationFailed 概率。
type Result ¶
type Result struct {
// Name Saga 名。
Name string
// Status 终态。
Status Status
// Err 触发补偿的原始失败(StatusCommitted 时为 nil)。
Err error
// FailedStep 失败步骤名(StatusCommitted 时为空)。
FailedStep string
// Steps 各步骤执行明细(按注册顺序)。
Steps []StepResult
}
Result 是 Execute 的完整结果。
type Saga ¶
type Saga struct {
// contains filtered or unexported fields
}
Saga 一个 Saga 编排:一组有序步骤 + 补偿策略。零值不可用,用 New 构造。