线上回滚策略
问题
新版本上线后发现问题,如何快速回滚?代码、SQL、配置分别怎么回滚?
答案
回滚决策流程
代码回滚
K8s 回滚
# 查看部署历史
kubectl rollout history deployment/order-service
# 回滚到上一个版本
kubectl rollout undo deployment/order-service
# 回滚到指定版本
kubectl rollout undo deployment/order-service --to-revision=5
# 查看回滚状态
kubectl rollout status deployment/order-service
Docker 回滚
# 重新指向上一个镜像
docker stop order-service
docker run -d --name order-service registry/order-service:v1.2.3 # 旧版本 tag
SQL 回滚
SQL 回滚最危险
数据变更一旦执行,回滚成本远高于代码回滚。关键原则:数据变更必须有回滚 SQL 且先备份。
DDL 回滚
-- 变更:添加列
ALTER TABLE orders ADD COLUMN remark VARCHAR(200);
-- 回滚 SQL(提前准备好)
ALTER TABLE orders DROP COLUMN remark;
DML 回滚
-- 变更前先备份
CREATE TABLE orders_backup_20240115 AS SELECT * FROM orders WHERE status = 1;
-- 执行变更
UPDATE orders SET status = 2 WHERE status = 1 AND create_time < '2024-01-01';
-- 如需回滚
UPDATE orders o
INNER JOIN orders_backup_20240115 b ON o.id = b.id
SET o.status = b.status;
数据变更规范:
- 变更 SQL 和回滚 SQL 必须成对出现
- DML 必须先备份受影响的数据
- 大批量更新分批执行
- 生产环境变更需审批
配置回滚
Nacos / Apollo 配置回滚
Apollo 管理界面 → 选择版本 → 一键回滚
Nacos:
配置管理 → 历史版本 → 选择回滚版本 → 回滚
灰度发布与快速回滚
灰度策略:
- 新版本部署少量实例(10%)
- 观察错误率、RT、业务指标
- 正常 → 逐步扩大流量比例
- 异常 → 立即将灰度流量切回旧版本
K8s 金丝雀发布
# 新版本 Deployment(少量副本)
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service-canary
spec:
replicas: 1 # 只起 1 个副本测试
回滚 Checklist
| 步骤 | 动作 |
|---|---|
| 1. 止血 | 立即回滚代码/配置 |
| 2. 验证 | 确认回滚后服务恢复正常 |
| 3. 通知 | 告知相关方 |
| 4. 排查 | 分析根因 |
| 5. 修复 | 修复后重新灰度上线 |
| 6. 复盘 | 完善流程避免再犯 |
常见面试问题
Q1: 上线出问题的第一反应是什么?
答案:
先止血,后排查。第一时间回滚恢复服务,而不是在线上 debug。回滚后再慢慢排查根因。
Q2: 如何减少上线风险?
答案:
- 灰度发布:小流量验证
- Feature Flag:代码合入但功能不开放,开关控制
- 向前兼容:新版本兼容旧数据格式
- 数据库先行:SQL 变更在代码上线前执行
- 可观测性:完善的监控和告警
Q3: 数据库变更如何做到可回滚?
答案:
- 添加字段:兼容旧代码,无需回滚
- 删除字段:先停止使用 → 观察 → 再删除
- 修改数据:备份 + 回滚 SQL
- 大表 DDL:在线 DDL 工具(gh-ost / pt-osc)