景泰拾伍.
首页 / 后端开发

接口超时之后,到底能不能重试?

API / 数据一致性   ·   整理于 2026-10-30

客户端收到超时,只能说明它没有及时拿到响应,不能说明服务端没有执行。创建任务的请求如果直接重发,可能得到两条相同的任务。

让一次业务操作拥有稳定的标识

客户端在用户开始一次创建操作时生成幂等键,网络重试沿用同一个键。用户明确发起另一次操作时才换新键。把生成逻辑写在每次重试函数里,就失去了去重效果。

POST /api/runs
Idempotency-Key: demo-operation-001
Content-Type: application/json

{ "agentId": "research_demo", "input": "整理接口文档" }

服务端不能只对这个字符串做全局查重。通常需要绑定已认证用户或租户、接口标识与请求内容摘要。相同键配上不同请求体,应明确拒绝,避免错误复用旧结果。

不要“先查再插”后就认为不会重复

两个请求可能同时查到“不存在”。最终需要数据库唯一约束兜底,并在一个事务里写入幂等记录和业务任务。

-- 表结构片段;字段和类型按实际数据库调整
UNIQUE (tenant_id, operation, idempotency_key)

BEGIN;
  INSERT INTO idempotency_records (...);
  INSERT INTO runs (...);
  UPDATE idempotency_records
     SET resource_id = :run_id, status = 'completed'
   WHERE ...;
COMMIT;

发生唯一键冲突后,重新读取已有记录。已完成就返回原资源或已保存的响应;正在处理则返回约定的处理中状态。具体用 202、409 还是轮询地址需要统一协议,不能让前端猜。

数据库事务覆盖不到外部动作

如果事务中调用外部服务,数据库回滚不会让已发送的外部请求撤销。可以用 outbox 把待发送事件和业务记录一起提交,再由 worker 投递;worker 仍可能重复投递,所以消费者也需要幂等处理。

外部服务支持幂等键时,把稳定的操作标识传过去。不支持时,需要业务唯一标识、查询结果或人工核对等补偿方案。仅靠本地去重表无法消除“外部成功、本地未记录”的窗口。

幂等记录也有生命周期

过期时间至少应覆盖客户端可能重试的窗口。记录清理后,同一个旧键可能再次创建资源,因此接口文档要写明有效期。请求指纹也应对校验后的规范化数据计算,避免字段顺序等无关差异造成误判。

← 返回文章列表