重试与补偿是什么
重试是自动再试一次,补偿是把已经发生的部分结果修正回去。重试成立的前提是操作可重复执行且结果一致,否则一次超时可能已经写入成功,重试会重复创建、重复扣费。设计上要做到四点:先给失败分类(瞬时错误与永久错误)、用指数退避加随机抖动避免同步重试、给重试设上限与总耗时预算、把重试范围限制在失败集合。当重试无法收敛时,走补偿路径:回滚已成功的部分,或转人工处理。
基本信息
| 常见参数 | Ansible retries/until/delay、curl --retry 与 --retry-all-errors、Kubernetes backoffLimit、parallel --retries |
|---|---|
| 退避策略 | 延迟按倍数增长并叠加随机抖动,同时设最大延迟上限 |
| 终止条件 | 重试次数、总耗时预算、错误类型白名单,三者取先到 |
| 前置要求 | 操作幂等,或通过幂等键与去重表保证重复执行无副作用 |
典型使用场景
- 网络抖动导致少量主机连接失败,退避后重试即有大概率成功
- 调用第三方接口遇到限流,按 Retry-After 退避后重试
- 批量任务部分主机失败,只对失败集合重跑
- 部署脚本需要等待目标服务启动完成,用轮询重试替代固定睡眠
- 不可重试的操作失败后,触发回滚把已变更部分收敛
重试与退避写法
重试与退避写法
curl --retry 3 --retry-delay 1 --retry-all-errors -sS -o out.json https://api.example.com/x
n=0
until ssh -n "$h" 'systemctl is-active app'; do
n=$((n+1)); [ "$n" -gt 3 ] && { echo "$h 重试耗尽"; break; } # 重试上限,避免无限循环
sleep $(( (2**n) + RANDOM % 3 )) # 指数退避 + 抖动
done
ansible-playbook deploy.yml --limit @failed.txt # 只重试失败集合错误类型与重试判定
| 错误类型 | 是否可重试 | 处理方式 |
|---|---|---|
| 连接超时、连接被重置 | 可 | 指数退避加抖动后重试 |
| HTTP 429 与 503 | 可 | 尊重 Retry-After,同时下调发起速率 |
| 认证失败、权限不足 | 不可 | 修正凭据或授权后重跑 |
| 命令参数或语法错误 | 不可 | 修正命令本身,重试无意义 |
| 目标端资源耗尽 | 谨慎 | 先降并发或扩资源,否则重试加重负载 |
重试不能替代补偿。重试解决的是「这一次没成功」,而一批操作中常见的是「部分成功」状态(例如 30 台已改、20 台未改),这需要单独的收敛或回滚设计,而不是靠重试抹平。
重试风暴是被忽视的故障放大器:控制端与目标端在同一时刻都在重试,负载叠加可能让原本的瞬时问题变成持续故障。重试总量必须设预算,并保证有抖动打散。