打开网易新闻 查看精彩图片
很多工程师把重试机制当成万能创可贴——接口挂了?重试。超时了?重试。队列堵了?还是重试。但很少有人算过一笔账:当你的重试间隔是固定1秒、3次封顶,而下游服务已经半死不活时,你其实是在给濒死病人做心肺复苏,按一下他吐一口血。
Netflix前工程师Nora Jones在2017年的一次事故复盘里写过一句话:「我们以为重试是在帮系统恢复,其实是在帮它自杀。」当时他们的支付服务因为重试风暴,把原本只有20%故障率的下游,硬生生推到了100%不可用。更讽刺的是,故障恢复后,堆积的重试请求像水库泄洪一样冲进来,第二轮崩溃来得比第一次还快。
问题的根子在于指数退避(exponential backoff)被用成了摆设。很多人配置了退避,却给最大延迟加了封顶——比如最多等30秒。结果几千个客户端像约好了一样,在第30秒集体苏醒,瞬间把下游砸穿。这叫"雷鸣群"效应,AWS的S3在2008年就栽过这个跟头,但十六年后它还在各个代码库里反复上演。
真正管用的方案其实反直觉:随机抖动(jitter)。把固定的退避时间打散,让客户端醒来的时间点像撒豆子一样均匀分布。AWS后来公开的数据是,加了抖动的重试能把峰值流量削掉80%以上。但工程师们不爱用这个,因为调试日志看起来乱糟糟的,不像固定间隔那么"优雅"。
一位在Stripe干了七年的工程师最近在Bluesky上吐槽,说他审查过的代码里,十有六七的重试配置是直接从Stack Overflow抄的,参数连改都没改。而那些被抄了上万次的答案,写于2012年。
热门跟贴