失败恢复与幂等

失败恢复先查清任务停在哪里、是否已经产生副作用,再决定重试、继续还是停下;幂等让同一操作的重复请求不重复生效。

返回概念图谱 →

理解与应用

失败恢复是让中断或出错的任务回到明确状态的方法。幂等则是一种重要保证:对同一个逻辑操作重复提交,效果应与执行一次一致。两者在智能体调用外部工具时经常相遇,因为模型、网络、服务端和结果保存都可能在不同时间失败。

假设助手把更正发票附到 R-204 后,没有等到服务器响应。现在至少有两种可能:请求没到达,或者附件已经保存、响应在路上丢了。把超时直接当成“没有提交”并再交一次,就可能产生重复附件。先读回提交状态,或用服务端支持的同一幂等键重试,才能区分并处理这两种情况。

幂等键代表的是同一个业务意图,不是每次 HTTP 尝试。重试应保持键和关键参数不变;拿着旧键改发另一张发票,服务端应拒绝。实际实现还需要原子地处理并发请求、持久保存操作结果,并约定记录保留期限。只在进程内用一个字典记“做过了”,服务一重启就失去保证。

不是所有失败都值得重试。短暂限流或网络故障可以采用有上限的退避,参数错误、权限拒绝和永久失败则需要修正或停止。无法核实副作用时,应保留“结果未知”,而不是随便标成失败后补做。多个系统只完成前半段时,撤销或补偿也可能产生新的费用和影响,需要按原任务授权判断是否能执行。

关系速览
反思与迭代修正应用于 →失败恢复与幂等

对失败轨迹的复盘可支持恢复选择,但恢复还依赖持久状态和幂等机制。

人工确认约束 →失败恢复与幂等

重试不得绕过过期或范围变化后的确认,需要重新核验待执行动作。

失败恢复与幂等应用于 →智能体工作流

持久状态、重试预算和补偿操作让中断后的流程可检查地继续。

执行沙箱应用于 →失败恢复与幂等

隔离环境中的失败实验可验证恢复路径,避免直接损坏真实资源。

动手试一试:响应丢失后,重复请求不再新增附件

同一请求重复提交复用已有回执,改参数则被拒绝。这个单进程示例没有持久化、过期策略或并发控制,用来说明业务语义,不能直接充当生产幂等服务。

将代码保存为 example.py,使用 Python 3.10+ 运行 python3 example.py。仅使用标准库,无需密钥,不会调用外部模型。

Python 代码

receipts = {}
attachments = []
def submit(key, record, filename):
    params = (record, filename)
    if key in receipts:
        old_params, receipt = receipts[key]
        if old_params != params:
            return "拒绝:同一操作标识的参数发生变化"
        return receipt
    attachments.append(params)
    receipt = f"回执 {len(attachments)}"
    receipts[key] = (params, receipt)
    return receipt
print(submit("op-7", "R-204", "invoice-v2.pdf"))
print(submit("op-7", "R-204", "invoice-v2.pdf"))
print(submit("op-7", "R-204", "invoice-v3.pdf"))
print("实际新增附件数:", len(attachments))

运行结果

回执 1
回执 1
拒绝:同一操作标识的参数发生变化
实际新增附件数: 1

常见误区

  • 网络超时表示调用方没有拿到结果,不等于远端没有执行。
  • 每次重试都换一个新幂等键,会把重复尝试变成多个独立操作。
  • 自动撤销和补偿也可能有副作用,不能因为原步骤失败就默认获准执行。

前置与延伸

建议先读

相关概念

参考与版本

Apollo 原创讲解与教学示例。参考资料用于核对技术定义;核验日不代表资料的发布日期。