失败要回到明确状态
自助交付常常包含多步操作,任何一步失败都会留下中间状态。回退设计的目标是让失败后的环境要么回到初始状态,要么停在一个明确可继续的状态。做法是先识别有副作用的步骤,为每一步定义补偿动作,并明确哪些步骤无法补偿、需要人工接管。
基本信息
| 识别对象 | 有副作用的步骤及其顺序依赖 |
|---|---|
| 回退方式 | 补偿动作、整体重建、快照还原 |
| 状态记录 | 每步执行状态与已完成步骤清单 |
| 不可回退项 | 数据写入、对外通知、已释放的资源 |
| 验收要求 | 回退后校验环境与初始状态一致 |
典型使用场景
- 多步交付中断:按已完成步骤逆序执行补偿动作,避免残留半成品
- 资源创建失败:删除已创建的部分资源,避免占用配额却无法使用
- 配置生效失败:回滚配置并重新加载,恢复到变更前状态
- 通知已发出:通知无法撤回,需在回退后追加更正通知
- 无法回退时:明确升级路径与人工清理步骤,而不是停留在中间态
回退策略对照
| 策略 | 适用情形 | 代价 |
|---|---|---|
| 逆序补偿 | 步骤相对独立 | 需为每步实现补偿动作 |
| 整体重建 | 资源可快速重建 | 交付时间变长 |
| 快照还原 | 交付前可做快照 | 占用存储,还原影响范围大 |
| 人工接管 | 存在不可回退步骤 | 依赖人工,响应时间较长 |
逆序补偿与状态记录
逆序补偿与状态记录
# 每完成一步登记状态,失败时按逆序补偿已完成的步骤
state_write step=create_db status=done
if ! provision_app; then
echo failed-at-provision_app >> deliver.log
rollback_all # 从最近完成的一步开始回退
fi
rollback_all() {
grep status=done deliver.log | tac | while read -r line; do
./compensate.sh $line >> deliver.log # 每步对应的补偿动作
done
}回退必须校验,否则回退过程本身失败会留下更隐蔽的问题。校验内容至少包含资源是否已删除、配置是否已恢复、配额是否已释放,并把结果写入执行记录。
数据写入与对外通知通常无法回退。设计时应把不可回退步骤尽量放在流程末尾,减少失败时需要人工介入的范围,并在交付说明中明确告知用户。