重试把作品发了三遍:幂等键到底该怎么设计

举报
yd_293143657 发表于 2026/10/26 01:13:37 2026/10/26
【摘要】 网络抖动时自动重试,结果平台出现三条一模一样的作品。原因是每次重试都生成了新的请求标识。讲清幂等键的取值、生命周期,以及与业务唯一键的区别。

一、重试放大了重复

上传超时会重试,这本身没错。错在每次重试都重新生成随机 UUID 作为请求标识——在服务端看来,这是三个不同的请求,于是老老实实创建了三条记录,作品列表里出现三份同名条目,还得手工删。

幂等键的核心是:同一个业务意图,必须产生同一个键。随机数不满足这一点,它只能区分请求,不能识别意图。UUID 适合做日志关联 ID,不适合做幂等键。

二、键该由什么组成

推荐的构成是「主体 + 业务唯一标识 + 内容指纹」。主体是账号或租户 ID,业务唯一标识可以是种子、业务单据号,内容指纹取关键字段的哈希。三者拼起来,既不会撞,也能保证重试稳定。

如果业务本身有天然唯一键(订单号、工单号),直接用它,别自己发明。没有的话,用「主体 + 时间粒度 + 序号」也行,但要注意时钟回拨:用本地时间做粒度,机器时间跳变会造出重复键,保险做法是带上一个自增序号或状态机的步骤名。

三、服务端怎么用这个键

常见实现是存一张幂等表:键 + 状态 + 首次响应体 + 过期时间。收到请求先查表,命中且已完成就把首次响应原样返回(连 HTTP 状态码一起复用);命中但处理中就返回 409,或者让客户端轮询同一个键直到状态落定。

过期时间要大于客户端最大重试窗口,通常是业务超时的数倍。设太短,长尾重试会穿透;设太长,表会膨胀。落地时给键加唯一索引,用数据库的唯一约束兜住并发,别只靠「先查再写」——两个请求同时查空、同时写入,照样重复。

四、客户端要注意什么

第一,键要在发起第一次请求之前就生成并持久化,进程崩溃重启后还能复用同一个键,否则重试链路一断就退化成新建。第二,重试只针对可重试错误(超时、5xx、429),4xx 参数错误重试没有意义,只会把日志刷满。

还有一条最容易忽略:重试时请求体必须完全一致。如果中间改了字段却复用旧键,服务端收到的就是「同一个键、不同内容」,行为完全取决于实现,可能报冲突,也可能静默用第一次的旧数据覆盖你的新数据。

五、退避和超时要一起调

只加退避不改超时,等于把重试窗口拉长到网关的容忍边界之外。实测里网关读 body 大约 30 秒就断,客户端超时设 180 秒,第一次请求还在等,重试逻辑根本没机会触发。

合理的组合是:客户端超时略大于服务端预期处理时间(比如 60 秒),退避 1s/2s/4s 加抖动,总预算不超过网关上限的一半。顺序也要定死:先判断错误类型,再决定是否退避,最后才复用幂等键重发。

六、验收方法

最简单的验收是人为制造超时:把上传超时阈值调到 1 秒,跑一次上传,确认平台上只有一条记录。再人为让第一次请求成功但响应丢失(比如代理丢响应体),确认客户端拿到的是幂等返回而不是报错。

这两个场景覆盖了绝大多数线上事故,值得写进回归用例。顺带记一条:验收时要看「列表条数」,不是看「接口是否 200」——重复创建同样是 200 或 201,只有条数能暴露问题。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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