连夜睡服低管,后端回滚没你想的简单:网易如何用一套体系保障“无痛撤退”?

✅ 先回答后端是如何回滚的

你说得没错,前端回滚多数情况下确实简单粗暴------切流 + 容器下线 + 前端版本回退

但后端没这么轻松,网易的后端回滚策略,不是文件层面的替换操作,而是"状态感知 + 自动回退 + 数据安全控制"的一整套机制。


一、网易后端回滚的核心设计理念:

"回滚不是恢复代码,而是恢复系统状态。"

也就是说,代码只是一个维度,真正复杂的是数据结构/服务状态的回滚控制


二、具体策略体系如下:

层级 回滚关键点 网易处理方式
应用层 接口逻辑异常、请求失败 灰度监控指标自动触发回滚
容器层 镜像发布错误 镜像 tag 快照 + K8s 版本 label 回退
数据层 数据结构/格式变化 所有变更必须有 双写/双表/回滚脚本
服务层 微服务接口协议 每次发布必须保留 向下兼容性(多版本并存)

三、回滚的触发机制(自动 + 手动并存)

网易发布系统中内置了"发布守护服务",结合 Prometheus + Kafka 消息流判断是否回滚:

scss 复制代码
if (errorRate > 0.05 || apiDelay > 300 || cpuLoad > 90) {
  dispatch('ROLLBACK_SERVICE', { version: previousStableVersion })
}

监控平台一旦判定"异常升级",则立即:

  1. 发出 K8s 资源回滚指令
  2. 下发"健康流量剪裁"策略,只保留上线前那批稳定容器
  3. 自动切回上一个镜像 tag(stable-20250601

四、后端回滚特别要注意的数据问题:

很多系统不是因为代码出问题,而是数据结构出问题导致无法回滚,网易处理如下:

情况 网易策略
新字段上线 使用 JSON 字段 + 后端兼容解析(非强 schema)
表结构变更 双表策略,例如 user_v1 和 user_v2,灰度切流
数据初始化失败 使用 Flyway + Liquibase 做 schema 快照 + 脚本回滚

五、容器级回滚代码(示意)

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-service
spec:
  template:
    spec:
      containers:
        - name: user-service
          image: registry/netease/user-service:stable-20250601

运维自动脚本:

ini 复制代码
kubectl rollout undo deployment user-service --to-revision=17

✅ 总结:

  • 前端回滚是降版本资源 + 切流
  • 后端回滚是 镜像级回退 + 容器编排 + 数据结构双写 + 灰度流控联动
  • 真正复杂的是:如何保证状态机、数据结构和流量一致性恢复

"上线容易,撤退难。能无痛回滚的后端,才叫靠谱。"


详细聊一下 ,你以为的回滚:

css 复制代码
git reset --hard HEAD~1 && restart

一、实际上网易后端是这样的:

markdown 复制代码
1. 服务切流
2. 镜像 tag 回退
3. 多版本共存
4. 数据格式向下兼容
5. 分布式事务补偿

二、架构图:网易服务回滚流程

css 复制代码
graph LR
A[发布启动] --> B[监控检测]
B --> C{是否异常}
C --是--> D[回滚触发器]
D --> E[容器回退]
D --> F[服务路由切流]
D --> G[数据层补偿或忽略]
C --否--> H[继续灰度或全量]

三、网易常用回滚策略(代码+机制)

1)镜像级别回滚(最常用)

sql 复制代码
kubectl set image deploy/user-api user-api=registry/user-api:stable-20250601
  • 灰度发布使用 gray-xxx
  • 上线使用 stable-xxx
  • 每次上线打 tag,方便精确回滚

2)流量灰度切回旧版本(服务网关支持多版本)

arduino 复制代码
if (currentVersion.errorRate > 0.05) {
  gateway.routeTo('user-api', 'v20250601')
}
  • 所有版本共存
  • 路由系统支持按 uid/地区/vip 等流量打标签分流

3)数据结构双写 / 快照

sql 复制代码
-- 新字段双写:
ALTER TABLE user ADD COLUMN new_flag TINYINT DEFAULT 0;

-- 服务层支持双写:
UPDATE user SET new_flag = 1 WHERE uid = ?

-- 回滚时不读取新字段即可恢复

或使用双表:

lua 复制代码
user_info_v1   <---旧逻辑读取
user_info_v2   <---新逻辑验证中

四、分布式事务场景:网易如何回滚?

举例:用户付费失败,触发补偿机制:

scss 复制代码
async function placeOrder(uid) {
  try {
    await pay(uid)
    await updateBalance(uid)
  } catch (e) {
    await sendToCompensationQueue({ uid, reason: e.message })
  }
}
  • Kafka/Redis 队列收集失败记录
  • 后台补偿系统每小时回扫一遍
  • 采用 Saga 模式部分回退

五、总结一句话:

"回滚能力是系统工程,不是命令行能解决的事。"

网易后端回滚体系依赖于:

  • 标准化发布流程
  • 镜像与路由隔离
  • 数据结构设计冗余
  • 日志 + 监控 + 灰度联动

彩蛋:

"上线之前先想好怎么下线,这才是高级程序员。"

相关推荐
Wang's Blog9 分钟前
Monorepo架构: Nx Cloud 扩展能力与缓存加速
缓存·架构
一只帆記14 分钟前
SpringBoot EhCache 缓存
spring boot·后端·缓存
henujolly18 分钟前
网络资源缓存
前端
yuren_xia3 小时前
Spring Boot中保存前端上传的图片
前端·spring boot·后端
普通网友4 小时前
Web前端常用面试题,九年程序人生 工作总结,Web开发必看
前端·程序人生·职场和发展
站在风口的猪11086 小时前
《前端面试题:CSS对浏览器兼容性》
前端·css·html·css3·html5
JohnYan6 小时前
Bun技术评估 - 04 HTTP Client
javascript·后端·bun
shangjg36 小时前
Kafka 的 ISR 机制深度解析:保障数据可靠性的核心防线
java·后端·kafka
青莳吖7 小时前
使用 SseEmitter 实现 Spring Boot 后端的流式传输和前端的数据接收
前端·spring boot·后端
CodeCraft Studio8 小时前
PDF处理控件Aspose.PDF教程:在 C# 中更改 PDF 页面大小
前端·pdf·c#