跳到正文
Elaine Blog
返回

超时、重试、幂等、去重与退避

分布式系统、协调与消息

一次超时只表示“调用方没等到结果”,不表示服务端没执行。安全的调用策略必须把截止时间、有限重试和幂等一起设计,否则重试会把短暂抖动放大成全站故障。

Table of contents

Open Table of contents

五个术语是一条链

客户端超时后,付款服务可能已经扣款,只是响应丢了。因此写请求携带 Idempotency-Key,服务端在同一事务中保存键、请求摘要和结果。重复请求若摘要不同,应返回冲突而不是复用旧结果。

只重试可恢复故障

可以重试连接重置、限流和部分 5xx;不要重试参数错误、权限错误和确定性的库存不足。每次尝试还要满足“剩余截止时间足够”。建议设置最大尝试次数,并使用指数退避加随机抖动(jitter):

上限 = min(最大间隔, 初始间隔 × 2^(失败次数-1))
实际等待 = random(0, 上限)

随机抖动让大量客户端不会同时醒来。服务端若返回 Retry-After,应优先尊重它。整条链路只能由一层主动重试;网关、SDK 和业务服务同时重试 3 次,最坏会放大到 27 次。

运行故障实验

分布式系统实验室下载执行:

mvn -Dtest=DistributedMechanismsTest#retryStopsAfterSuccessAndUsesBoundedBackoff test

测试让前两次调用返回失败,第三次成功,同时验证等待上限不超过 150ms。教学模型不真的休眠,生产实现还应记录尝试次数、最终原因、剩余预算和幂等命中率。

常见错误是把数据库唯一键冲突吞掉后直接返回成功。正确做法是查询已保存结果并校验请求摘要;否则两个不同请求误用同一键时会掩盖数据错误。

下一步

继续阅读08-03 分布式 ID:趋势递增、时钟与号段,学习怎样为幂等请求和业务实体生成跨节点标识。


分享这篇文章:

上一篇
CAP、PACELC 与一致性模型
下一篇
分布式 ID:趋势递增、时钟与号段