幂等性
幂等性是确保同一操作执行多次和执行一次效果相同的工程实践。在 AI Agent 应用中,它防止网络重试导致的重复消息、重复工具调用和重复扣款。
#concept
#evergreen
#backend
#architecture
[!info] related notes
- 所属 MOC: AI Agent Application MOC
- 相关: Tool Idempotency, Retry Policy
幂等性
一句话定义
幂等性是确保同一操作执行多次和执行一次效果相同的工程实践。关键是同一逻辑操作的重复提交不产生额外业务副作用;用户有意发送两次相同内容应是两个操作。SSE 重连通常重放事件,不应自动重新执行对应命令。
它解决什么问题
网络不可靠:
- 用户双击发送按钮 → 两条相同消息
- 网络超时重试 → 重复调用工具
- SSE 断连重连 → 重复处理事件
- 工具执行成功但返回失败 → 重试导致重复执行(如重复扣款)
核心原理
幂等性实现方式
| 方式 | 原理 | 适用场景 |
|---|---|---|
| 稳定操作 ID | 同一操作的重试复用 ID,服务端按作用域去重 | API 请求 |
| 天然幂等 | 操作本身幂等(如 SET x=1) | 数据库操作 |
| 去重表 | 记录已执行的操作 ID | 工具调用 |
| 乐观锁 | 版本条件检测冲突,不自动重放之前结果 | 并发更新 |
幂等 Key 与持久执行协议
调用方为一个逻辑操作生成 operation_id;所有重试复用,同参数的新意图使用新 ID
服务端键范围 = tenant + actor/调用主体 + operation_type + operation_id
规范化参数并计算摘要:同 key 不同参数拒绝
以唯一约束或 CAS 原子创建 pending 记录;并发重复请求读取既有状态
同数据库副作用:在事务内完成业务修改并记录结果
外部副作用:向下游传递其支持的幂等 key,或用 outbox + 对账处理未知结果
完成后保存可重放的状态码、选定响应头和脱敏响应体
过期清理遵循业务重试窗口;明确过期 key 是否允许重新执行
常见坑
- 不做去重: 用户双击导致重复消息
- 工具不幂等: 重试导致重复扣款
- 去重 Key 不传递: 前端生成了 Key 但后端没用
- 去重窗口太短: 重试时间超过了去重窗口
- 先查再写缓存:并发请求可同时执行;执行成功后保存结果前崩溃也会产生重复
- 把超时当失败:下游可能已完成,此时状态应标为未知并对账,而不是无条件重试
- 跨用户复用缓存:每次重放仍需鉴权,不能仅凭 key 读取他人的结果