事件重试与补偿需形成闭环:重试用于可恢复异常(如网络超时),须配指数退避(1s→2s→4s→8s→16s→30s)和3–5次限制;不可恢复异常(如参数错误)应直触补偿,补偿须幂等、有状态标记,并基于业务ID校验真实状态,全程留痕可追溯。

事件重试机制不是“失败就重试”那么简单,它需要和补偿逻辑形成闭环:重试是尝试恢复,补偿是兜底确认。关键在于区分可恢复异常与不可恢复异常,并在重试耗尽后自动转向补偿动作。
识别哪些失败该重试、哪些该直接补偿
不是所有失败都适合重试。盲目重试可能放大问题甚至引发雪崩。
- 适合重试的场景:网络超时、第三方服务临时不可用、数据库连接抖动、限流拒绝(HTTP 429)——这类问题大概率随时间自行恢复
- 应跳过重试、直触补偿的场景:数据格式错误(如 JSON 解析失败)、业务规则校验不通过(如余额不足)、非法参数(如空 ID)——这些错误不会因重试而改变,反复执行只会重复失败
配置带退避策略的重试,避免打垮下游
重试必须配合指数退避(Exponential Backoff),防止瞬间重压击穿依赖方。
- 初始延迟建议 1–2 秒,倍数设为 2,最大延迟不超过 30 秒(例如:1s → 2s → 4s → 8s → 16s → 30s)
- 总重试次数控制在 3–5 次以内;超过即视为“已尽力”,进入补偿流程
- Spring Boot 中可用
@Retryable配合@Backoff实现,同时用@Recover方法定义补偿入口
补偿逻辑要能独立执行且幂等
补偿不是“再跑一遍原逻辑”,而是根据失败上下文执行确定性修复动作。
- 补偿操作需自带事务边界或状态标记(如写入补偿任务表并记录 status=‘pending’),避免重复触发
- 常见补偿类型包括:调用反向接口(如支付失败则释放冻结金额)、更新本地状态为失败并通知人工介入、将事件转存至死信队列供离线分析
- 若原事件含唯一业务 ID(如 order_id),补偿方法应基于该 ID 查询最新状态,确认是否真需补偿,防止“已成功但网络未返回”的误补偿
把重试与补偿串联成可追踪的执行链
每一次重试、每一次补偿都应留下完整轨迹,便于排查和审计。
- 记录每次重试的时间、异常类型、输入快照;补偿执行时也记录决策依据(如“第5次重试失败,触发 cancel_inventory 补偿”)
- OpenClaw 等框架支持 DAG 节点级状态追踪,可将重试节点与补偿节点作为不同分支纳入同一工作流,实现可视化编排
- TCC 类事务中,补偿常对应 confirm/cancel 两路操作;此时补偿逻辑本质是状态机驱动的确定性终态推进

















