接口幂等设计:重试安全与去重键的落地细节

举报
yd_257405204 发表于 2026/10/29 09:14:46 2026/10/29
【摘要】 一次网关超时,前端自动重试,用户却收到了两笔订单。排查下来,下单接口本身没有幂等保护:第一次请求其实已经写库成功,只是响应在回程丢了。这类问题在微服务和移动端弱网环境里非常常见。 超时不等于失败 调用方看到 timeou

一次网关超时,前端自动重试,用户却收到了两笔订单。排查下来,下单接口本身没有幂等保护:第一次请求其实已经写库成功,只是响应在回程丢了。这类问题在微服务和移动端弱网环境里非常常见。

超时不等于失败

调用方看到 timeout,只能确定“没等到响应”,不能确定“服务端没执行”。因此任何可能被重试的写接口,都必须假设自己会被调用多次。重试策略越积极,幂等设计就越不能省。

幂等键放在哪一层

推荐由客户端生成一个 request_id(UUID 或“业务单号+动作”),随请求头传入;服务端在同一个事务里写业务表和去重表,去重表对 (tenant_id, request_id) 建唯一索引。重复请求撞到唯一键时,不再执行业务,而是返回第一次的结果。

不要在网关层用 URL+body 做哈希:字段顺序、时间戳、灰度参数都会让同一个业务请求算出不同指纹;也不要让服务端自己生成键,那样重试时根本对不上。

处理中的请求怎么返回

如果第一次请求还在执行,第二次请求会看到“记录已存在但状态是处理中”。此时应返回 409 或 202,并带上查询进度的地址,而不是傻等或直接报错。等到第一次完成,再把结果补进去重记录,后续重试就能拿到稳定响应。

去重记录保留多久

至少覆盖“客户端最大重试窗口 + 人工补偿窗口”。按天分表、保留 7~30 天通常够用;金融类场景按审计要求延长。清理任务要和业务写入解耦,避免大表删除拖慢主库。

别把幂等做成全局锁

用 Redis 的 SETNX 做短期防重可以,但只能当第一道闸,最终一致性仍要落到数据库唯一约束。锁过期时间设得太短,长事务会漏;设得太长,失败请求会长期占坑。数据库唯一键加状态机才是兜底。

一份检查清单

  • 所有写接口是否声明了幂等键来源;
  • 唯一索引是否包含租户维度,避免跨租户碰撞;
  • 重复请求返回的是首次结果还是模糊报错;
  • 处理中状态是否有超时回收;
  • 去重记录过期后,重试会不会重新执行。

幂等不是给接口加一个“防重复”开关,而是把“可能重复”当成常态来设计。把键、状态和过期策略三件事定清楚,重试才真正安全。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。