重试是把放大器:什么时候能重试、该退避多久、以及为什么总在最后变成雪崩

举报
yd_238022924 发表于 2026/11/04 00:30:10 2026/11/04
【摘要】 重试是系统里最强的放大器。本文讲清三个可重试的前提、指数退避为什么必须有抖动、超时与重试的次数怎么一起算,以及为什么该用「重试预算」而不是单请求次数限制来止血。

重试是把放大器:什么时候能重试、该退避多久、以及为什么总在最后变成雪崩

「这个接口偶尔超时,加重试吧」——这句话在线上事故里的出场频率,大概仅次于「加个缓存吧」。

重试本身没错,错在很多人把它当成一个局部的小修补。实际上重试是系统里最强的放大器:一次用户请求,可能在下游被放大成几次、几十次调用。放大倍数不受控,重试就从"提高可用性"变成"制造雪崩"。

一、先判断能不能重试

重试有三个前提,缺一个就不该重试:

第一,操作必须幂等。 查询天然幂等;扣款、下单、发消息不是。给一个非幂等接口加重试,失败场景下就是重复扣款。要么先把接口做成幂等(幂等键、去重表、状态机),要么干脆不重试。

第二,错误必须是瞬时的。 连接被重置、DNS 临时失败、下游短暂过载,这些重试一次大概率能好。而参数校验失败、权限不足、404 这类确定性错误,重试一百次结果都一样,只是把错误放大了一百次。

第三,次数和时间必须有界。 很多事故的根源是"无界重试"——一个请求在链路里层层重试,最终把本来只是慢的下游彻底打死。

判断口诀很简单:确定性错误别重试,非幂等操作别重试,没有退避的重试不如不重试。

二、指数退避和抖动,缺一不可

固定间隔重试的问题不在于慢,而在于同步。假设下游在某一瞬间抖动,一万个客户端同时在 100ms 后重试,下游面对的还是同样的一万并发——只是晚了一点。这就是"重试风暴"。

标准解法是指数退避配合随机抖动:

第 n 次重试的等待 = min(基准 × 2^n, 上限) × random(0.5, 1.5)

那个随机因子就是抖动。它把本来整齐划一的重试打散,让下游承受的是平滑的尾部流量,而不是一堵墙。没有抖动的指数退避,仍然是同步的,这一点很多人漏掉。

另外一定要有上限。2^n 涨得很快,不封顶的话第 10 次重试要等十几分钟,那时候用户早就走了;而连接还占着,反而浪费资源。

三、超时和重试必须一起算

这是最容易出事的地方:上层的总超时,必须大于"单次超时 × 最大重试次数",否则上层早就超时返回了,下层的重试还在跑——用户看到的是失败,系统里却还在持续加压。

反过来的错误也常见:只给下游设了很短的单次超时,却没给总时长设限,于是一个请求在重试链里耗掉几十秒,把线程池全占了。

实用的做法是给每个请求带一个剩余时间预算:进链路时算出一个 deadline,每次重试前检查还剩多少,不够就直接放弃并快速失败。这样无论重试几层,总耗时都是可控的。

四、重试预算:把重试本身当成一种资源

更好的做法不是限制"每个请求重试几次",而是限制"整个集群拿多少流量去重试"。

思路是:正常情况下重试占比很低(比如 1%),一旦超过阈值(比如 10%),说明下游已经在系统性故障,此时不是重试能救的,应该直接快速失败、让熔断器接管。这就是重试预算(retry budget)——它比单请求次数限制更能反映系统真实状态。

配合熔断,效果更好:连续失败到阈值就跳过重试直接失败,过一段时间放少量请求试探。重试解决的是偶发,熔断解决的是持续,两者分工不同,不能互相替代。

五、重试要有观测

没有观测的重试是隐形炸弹。至少要有三个指标:

  • 重试率:被重试的请求占总请求的比例。它突然上升,通常比错误率更早暴露问题。
  • 重试成功率:重试里有多少最终成功。这个数字很低,说明重试在做无用功,只是在放大流量。
  • 重试放大倍数:一次用户请求平均产生多少次下游调用。这个值大于 2 就值得警惕了。

还有个容易忽略的:日志里要能看出"这是第几次重试"。否则排查时看到的是一堆重复请求,根本分不清是并发还是重试。

六、几个务实的小建议

  • 给重试加开关,并且能在不改代码的情况下关掉。事故时第一件事往往就是"先把重试停了"。
  • 重试只在入口层和最外层做,中间层不要层层重试。每一层都"好心"重试一次,放大倍数就是指数级。
  • 异步任务的重试要配合死信队列,失败到一定次数就落盘,别无限循环。
  • 对于写操作,宁可返回"处理中 + 稍后查询",也不要盲目重试。

重试写起来只有几行,但它改变的是系统的流量特性。把它当成一个需要预算、需要退避、需要观测的机制,而不是一个 try-catch 里的循环,才是它真正该有的地位。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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