DOCAI · 概念 · L3
幂等是什么,为什么重试前要谈幂等
同一个请求执行一次和执行多次,系统最终状态相同;这是安全重试的前提。
它是什么
幂等原本是 HTTP 语义里的概念:同一个操作执行一次和执行多次,对系统状态的影响相同。重复提交不会多扣一次款。
两个限定要抓住。第一,幂等说的是最终状态,不是响应完全一样:第二次可以返回「已处理」,但不能再产生新副作用。第二,幂等针对副作用,不针对计算过程:模型可以被调用很多次,只要计费、写库、发消息只发生一次。
LLM 调用卡在两者之间。生成文本不改变外部状态,但一次请求会计费、写日志;如果模型触发工具调用,还会真正发邮件、改数据库、下单。于是重试从文本问题变成了副作用问题。
怎么工作
幂等键。 调用方为一次业务操作生成唯一标识,放进请求头或请求体。同一个标识重复到达,服务端知道这是「同一次操作」。有的厂商在 API 层支持这个字段;没有提供时,就在自己的网关或业务层实现,不能指望模型端去重。
去重表。 把幂等键、请求摘要、处理状态和结果存进带唯一约束的表。收到请求先查表:成功就返回保存的结果;处理中就让调用方等待;从未见过才执行。关键点是「占位」和「执行」在一个原子操作里完成,否则并发请求会同时通过检查。
超时后的查询。 超时是最难处理的失败:你不知道上游到底执行了没有。不要立刻重试,先用幂等键或业务标识查询结果。如果第一次其实成功了,重试就是第二次副作用;查不到再带同一个键重试。限流错误通常可以重试,但也要走同一套去重逻辑——限流只说明这次被挡了,不说明上一次没执行。
工具调用隔离副作用。 模型输出的是调用意图,不是执行结果。执行层给每个工具调用分配稳定标识并持久化;收到重复请求时复用上次结果,而不是再执行一遍。工具本身也要尽量幂等:写状态而不是累加,按业务主键更新而不是盲目插入,发消息带客户端生成的消息标识。
常见误解
「只是生成文本,重试没关系。」 生成也计费、也留记录;响应里带工具调用时,重试会把工具执行两次。
「幂等键是厂商该管的事。」 厂商支持就省事,不支持就得自己做。跨供应商时不能假定语义一致。
「重试就是再发一遍请求。」 没有去重表的重试只是重复执行。正确顺序是:判断错误类型,查询上次结果,再用同一个幂等键重试。
「幂等等于响应一模一样。」 第二次返回「已处理」也是幂等。判断标准是副作用有没有叠加。
怎么排查
- 账单或记录重复:看重试路径有没有绕过去重表,超时后是否直接重试。
- 工具被执行两次:检查调用标识是否持久化,并发请求是否同时通过「未执行」检查。
- 去重表挡不住并发:确认唯一约束和占位操作是否原子,别用「先查后写」。
- 重试后仍失败:区分限流、超时和服务端错误;排查思路见读懂一次 API 报错。
什么时候用
请求可能被重复投递时都要考虑:客户端自动重试、消息队列至少一次投递、流式连接中断后重连、Agent 的工具循环、人工点「再试一次」。纯查询可以简化,但查询也可能计费,仍要限制重试次数。
什么时候用得上
当你给 API 调用加重试、处理超时补偿,或在 Agent 里让模型触发工具时,先设计幂等,否则一次失败重试就可能把副作用放大。
常见误解
很多人以为「重试一次而已,最多多花一点 token」。实际上重试可能重复计费、重复写库、重复发消息。LLM 请求本身不幂等,必须由调用方用幂等键和去重表兜底。