幂等回滚要满足什么
回滚有两个容易踩空的前提:一是回滚动作本身要幂等,先查现场状态再决定动不动作,重复执行不改变结果;二是要承认有些变更不可回退——数据写入、结构变更、证书吊销大多只能前滚(用修复往前推进),不能靠回退解决。批量回滚还应保持逆序与分批:后改的先退,避免依赖被提前撤掉;分批回退则避免所有节点同时回到旧版本后容量骤降。回滚方案要在变更前演练,不能等故障时才第一次执行。
基本信息
| 回滚对象 | 配置回滚、版本回滚、数据变更(多数不可逆,需前滚方案) |
|---|---|
| 幂等做法 | 先查当前状态,仅在偏离目标时动作,动作可重复执行 |
| 执行顺序 | 逆序回退,后改的先退;分批回退,避免容量骤降 |
| 关键约束 | 回滚须有超时与人工兜底,事先演练而非临时编写 |
典型使用场景
- 分批发布失败:回退已发布批次,同时冻结后续批次
- 配置批量下发失败:一部分主机已生效,另一部分未生效
- 灰度验证不通过:只回退灰度批次,全量尚未开始
- 数据库结构变更:确认不可回退后改用前滚修复方案
- 缓存与索引重建失败:保留旧版本继续服务,清理半成品
- 回滚中途失败:可安全重跑,不用先判断上次退到哪一步
幂等且逆序的回滚
幂等且逆序的回滚
# 单机回滚:先查当前指向,已在目标版本就跳过,保证可重复执行
rollback_one() {
host="$1"
cur=$(ssh -n "$host" 'readlink -f /opt/app/current' || true)
if [ "$cur" = "/opt/app/releases/v1.4.0" ]; then
echo "$host 已是目标版本,跳过"
return 0
fi
ssh -n "$host" 'ln -sfn /opt/app/releases/v1.4.0 /opt/app/current && systemctl reload app'
}
# 逆序回滚:后改的先退,避免依赖被提前撤掉
for h in $(tac changed-hosts.txt); do
timeout 60 bash -c "rollback_one $h" \
|| echo "$(date -u +%FT%TZ) $h 回滚失败,需人工处理" >> rollback-err.log
done
# 回滚完成后回读校验:确认版本、进程与端口状态都回到基线变更类型与回滚手段
| 变更类型 | 可否回退 | 回滚手段 | 主要风险 |
|---|---|---|---|
| 配置文件 | 可以 | 还原上一版本并重载 | 未重载导致看似回滚实则未生效 |
| 应用版本 | 可以 | 切回旧版本目录并重启 | 新旧版本依赖不兼容 |
| 数据写入 | 通常不可 | 前滚修复或用备份恢复到时间点 | 回退可能丢数据 |
| 结构变更 | 多数不可 | 前滚补丁或反向结构脚本 | 中间态无法服务 |
| 证书与密钥 | 受限 | 恢复旧证书需注意吊销状态 | 已吊销证书不能再用 |
回滚与前滚的选择标准是「哪种方式更快恢复服务」。当前滚补丁几分钟能修好、回滚要走数据恢复且丢数据时,前滚通常更合适;决策应在变更前就写进方案,而不是在故障中临场讨论。
回滚过程中会出现新旧并存的中间态:一半节点已退、一半未退,接口兼容与数据格式可能都不成立。评估回滚方案时要把这段窗口的风险单独算一遍。