重试与退避
指数退避、jitter、幂等前提。
30 分钟
重试与退避
瞬时网络抖动、TCP 重传、MySQL 死锁——短暂失败 用 有限次重试 往往有效。但若下游 真挂 或 过载,盲目重试会制造 retry storm,加速级联失败。
学习目标
- 掌握指数退避、jitter、最大重试次数
- 理解 幂等 是重试的前提
- 对照 Spring Retry / Resilience4j 配置
何时重试
| 适合重试 | 不宜重试 |
|---|---|
| 连接超时、502/503 | 400 参数错误、401/403 |
| 可幂等的读请求 | 非幂等写(未做去重) |
| 明确 transient 错误 | 下游已熔断 OPEN |
幂等设计见 ip-idempotency。
退避策略
第 1 次失败 → 等 100ms
第 2 次失败 → 等 200ms
第 3 次失败 → 等 400ms
...
+ jitter(随机 ±30%)避免齐步重试
指数退避 + jitter 把重试分散开,减轻下游压力。
# Resilience4j Retry 示例
resilience4j:
retry:
instances:
mysql-call:
maxAttempts: 3
waitDuration: 200ms
exponentialBackoffMultiplier: 2
enableRandomizedWait: true
完整熔断组合见 sc-circuit-breaker。
架构位置
[Client / 浏览器] ← 勿无限重试
│
[Nginx] ← proxy_next_upstream 有限次
│
[backend] ← @Retryable / RestTemplate 配置
│
[MySQL] ← 死锁可重试,连接拒绝则熔断
每一层都重试 = 乘法放大:3 层 × 3 次 = 27 倍流量。
CodeRoadMap 实践
- 对外 API:客户端错误 不重试;5xx 最多 1~2 次 + 退避
- 写操作:依赖 幂等键 或 DB 唯一约束后再重试
- 监控重试率:
resilience4j_retry_calls_total(prom-spring)
练习
- 计算三层各重试 3 次时的最大请求倍数
- 说明 POST 创建订单为何需要幂等才能重试
- 配置 maxAttempts=3 并观察日志
小结
重试治抖动,退避防风暴;幂等保安全。 下一课:超时与 deadline。