首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >数据备份做得再勤快,没做过这件事,真出事还是得抓瞎

数据备份做得再勤快,没做过这件事,真出事还是得抓瞎

原创
作者头像
Echo_Wish
发布2026-09-03 08:10:19
发布2026-09-03 08:10:19
340
举报

数据备份做得再勤快,没做过这件事,真出事还是得抓瞎

RPO 决定你最多能丢多少数据,RTO 决定你多久能把业务救回来。

但真正决定一家公司的备份方案能不能扛住事故的,往往不是“备份了多少次”,而是——跨区域恢复演练到底做没做。

我是 Echo_Wish。

干运维这些年,我越来越觉得,数据备份是一件特别容易产生错觉的事情。

每天凌晨备份成功。

监控显示绿色。

备份任务显示 SUCCESS

对象存储里躺着几十 TB 的备份文件。

老板问:

“数据应该没问题吧?”

运维:

“没问题。”

直到某一天,生产数据库真的挂了。

然后你会发现:

备份文件有。

但是恢复账号没权限。

密钥找不到。

备份版本不兼容。

跨区域网络没打通。

DNS 切不过去。

应用配置没备份。

数据库恢复了,但业务起不来。

最后大家才发现:

我们备份的是数据,却没有备份“恢复能力”。

这就是今天想聊的核心:

备份不是目的,恢复才是目的。


一、先搞明白:RPO 和 RTO 到底是什么?

很多刚接触运维的朋友,一看到 RPO、RTO 就头大。

其实特别简单。

RPO:最多允许丢多少数据?

RPO,全称:

Recovery Point Objective,恢复点目标。

你可以把它理解成:

“最坏情况下,我能接受丢掉多久的数据?”

比如:

数据库每 1 小时备份一次。

那么理论上最坏情况下可能丢 1 小时的数据。

所以:

代码语言:text
复制
RPO ≈ 1小时

如果业务要求:

最多只能丢 5 分钟的数据。

那每小时备份一次肯定不够。

可能需要:

代码语言:text
复制
全量备份
+
增量备份
+
WAL/binlog/redo log
+
持续复制

最终做到:

代码语言:text
复制
RPO <= 5分钟

二、RTO 更现实:多久能恢复业务?

RTO:

Recovery Time Objective,恢复时间目标。

简单说就是:

“生产挂了以后,我最多允许业务瘫痪多久?”

比如:

代码语言:text
复制
RTO = 4小时

意味着:

从事故发生开始,4 小时以内必须把业务恢复。

如果是普通内部系统:

代码语言:text
复制
RPO = 24小时
RTO = 24小时

可能都能接受。

但如果是:

代码语言:text
复制
支付系统
交易系统
电商核心订单系统
制造业生产系统

你告诉业务:

“数据库坏了,24 小时后恢复。”

估计老板能直接把你从机房送出去。

所以不同业务,RPO/RTO 完全不一样。


三、备份策略其实经历了三个阶段

我个人觉得,企业的备份策略,大概经历了三个阶段。

第一阶段:能备份就行

最传统的方案:

代码语言:text
复制
每天凌晨 2 点
        ↓
数据库全量备份
        ↓
保存 7 天

脚本可能长这样:

代码语言:bash
复制
#!/bin/bash

DATE=$(date +%Y%m%d)

mysqldump \
  -h 127.0.0.1 \
  -u backup \
  -p'******' \
  production_db \
  > /backup/mysql_${DATE}.sql

然后:

代码语言:bash
复制
crontab -e

每天执行。

这个阶段的核心目标只有一个:

别把数据弄丢。

对于小系统来说,其实完全够用。


四、第二阶段:开始考虑 RPO/RTO

系统规模上来之后,问题就来了。

每天一次备份:

代码语言:text
复制
00:00
   ↓
备份
   ↓
01:00
   ↓
业务写入
   ↓
02:00
   ↓
数据库挂了

这时候你会发现:

代码语言:text
复制
01:00 ~ 02:00

这一个小时的数据可能全部没了。

于是企业开始引入:

代码语言:text
复制
全量备份
+
增量备份
+
日志备份

比如:

代码语言:text
复制
每天 02:00
    ↓
全量备份

每 10 分钟
    ↓
增量备份

持续
    ↓
binlog/WAL

这样恢复时:

代码语言:text
复制
全量备份
    +
增量备份
    +
日志
    ↓
恢复到故障前

RPO 就能从:

代码语言:text
复制
24小时

降低到:

代码语言:text
复制
10分钟

甚至更低。


五、第三阶段:真正开始考虑“跨区域”

这里才是我认为最容易被忽略的地方。

很多公司会说:

“我们已经做异地备份了。”

我问一句:

“异地在哪里?”

对方:

“另一台服务器。”

我继续问:

“在哪个机房?”

对方:

“就在隔壁机房。”

这其实不叫真正意义上的跨区域灾备。

如果发生的是:

代码语言:text
复制
单机故障

没问题。

如果发生:

代码语言:text
复制
数据库实例故障

也可能没问题。

但是如果发生:

代码语言:text
复制
机房断电
网络中断
区域级故障
云厂商区域故障
自然灾害
人为误操作
勒索软件

那么:

代码语言:text
复制
A机房挂了
↓
B机房也一起挂

你的“异地备份”就变成了:

异地了个寂寞。

真正的跨区域架构应该尽量做到:

代码语言:text
复制
Region-A
生产环境
    │
    │ 数据复制
    ↓
Region-B
灾备环境

例如:

代码语言:text
复制
            ┌──────────────┐
            │  Region A    │
            │  Production  │
            └──────┬───────┘
                   │
             数据复制/备份
                   │
                   ↓
            ┌──────────────┐
            │  Region B    │
            │   DR Site    │
            └──────────────┘

这样 Region A 真挂了:

代码语言:text
复制
Region A
   ↓
故障
   ↓
切换
   ↓
Region B
   ↓
恢复业务

六、但是有个非常残酷的问题:你确定真的能恢复吗?

这是整个备份体系里,我最想强调的一件事情。

备份成功 ≠ 恢复成功。

举个非常现实的例子。

你的备份目录:

代码语言:bash
复制
/backup/
├── mysql_20260801.sql
├── mysql_20260802.sql
├── mysql_20260803.sql
├── mysql_20260804.sql
└── mysql_20260805.sql

监控:

代码语言:text
复制
SUCCESS
SUCCESS
SUCCESS
SUCCESS
SUCCESS

看起来非常漂亮。

但是恢复的时候:

代码语言:bash
复制
mysql production < mysql_20260805.sql

结果:

代码语言:text
复制
ERROR 1045
Access denied

数据库账号没了。

重新配置。

继续恢复:

代码语言:text
复制
ERROR 1044
Access denied for database

权限又没了。

折腾半天终于恢复数据库。

结果应用启动:

代码语言:text
复制
Connection refused

因为:

代码语言:text
复制
数据库 IP
Redis IP
MQ 地址
对象存储地址
配置中心地址

全部还是生产环境地址。

你会发现:

数据库恢复了,但系统没恢复。

这就是为什么灾备必须从:

Data Recovery

升级到:

Service Recovery。


七、所以真正的灾备,应该备份这五类东西

很多人备份的时候只盯着数据库。

其实至少应该考虑:

1. 数据

代码语言:text
复制
MySQL
PostgreSQL
Oracle
MongoDB
Redis

2. 配置

代码语言:text
复制
Nginx
应用配置
数据库配置
Kafka
Redis
MQ
配置中心

3. 基础设施

如果你使用 Kubernetes,更应该考虑:

代码语言:text
复制
Namespace
Deployment
Service
ConfigMap
Secret
PVC
Ingress

例如:

代码语言:bash
复制
kubectl get deploy -A -o yaml > deploy.yaml
kubectl get svc -A -o yaml > service.yaml
kubectl get configmap -A -o yaml > configmap.yaml

当然,生产环境不建议简单粗暴地把所有资源直接 dump 出来当完整灾备方案。

更合理的是:

代码语言:text
复制
Git
    ↓
IaC
    ↓
Terraform / Ansible
    ↓
Kubernetes Manifest
    ↓
自动化重建

也就是说:

服务器可以没,但环境必须能重新造出来。


八、跨区域恢复最重要的,不是“备份”,而是“演练”

这句话我建议所有运维人员都记住:

没有经过恢复验证的备份,本质上只是“看起来存在的数据”。

所以企业应该定期进行:

代码语言:text
复制
Backup
   ↓
Restore
   ↓
Validate
   ↓
Failover
   ↓
Business Verification

比如每季度做一次真正的灾备演练。

模拟:

代码语言:text
复制
Region A 整体不可用

然后按照真实事故流程执行。


九、一次完整的跨区域恢复演练应该怎么做?

我建议至少按照下面这个流程。

第一步:宣布灾难

例如:

代码语言:text
复制
10:00

Region A:
数据库不可用
应用不可用
网络不可用

这时候不要直接偷偷恢复。

而是按照真正的事故流程:

代码语言:text
复制
告警
 ↓
值班响应
 ↓
事故确认
 ↓
启动灾备预案

第二步:确认 RPO

例如:

代码语言:text
复制
最新备份:
09:55

故障时间:
10:00

那么:

代码语言:text
复制
RPO = 5分钟

检查:

代码语言:text
复制
09:55
09:50
09:45

的数据是否完整。


第三步:启动 Region B

比如 Kubernetes:

代码语言:bash
复制
kubectl config use-context region-b

kubectl apply -f namespace.yaml
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

然后:

代码语言:bash
复制
kubectl get pods -A

确认:

代码语言:text
复制
Running
Running
Running

十、数据库恢复之后,千万别马上宣布“恢复成功”

数据库能连上,只能说明:

数据库活了。

不代表:

业务活了。

应该继续执行业务验证。

例如:

代码语言:bash
复制
curl http://api-dr.example.com/health

然后:

代码语言:bash
复制
curl \
  -X POST \
  http://api-dr.example.com/order/create

检查:

代码语言:text
复制
创建订单
查询订单
修改订单
支付
库存扣减
消息发送

最终形成:

代码语言:text
复制
基础设施恢复
       ↓
数据库恢复
       ↓
应用恢复
       ↓
接口恢复
       ↓
核心业务恢复
       ↓
用户访问恢复

这才叫真正的恢复。


十一、甚至可以把灾备演练自动化

如果每次灾备演练都靠:

代码语言:text
复制
张三恢复数据库
李四改配置
王五改 DNS
赵六检查接口

那迟早要出问题。

可以逐步自动化。

例如:

代码语言:python
复制
import requests
import time

def check_service(url):
    try:
        r = requests.get(url, timeout=5)

        if r.status_code == 200:
            print(f"[OK] {url}")
            return True

        print(f"[FAIL] {url}: {r.status_code}")
        return False

    except Exception as e:
        print(f"[ERROR] {url}: {e}")
        return False


services = [
    "https://dr.example.com/health",
    "https://dr.example.com/api/order/health",
    "https://dr.example.com/api/inventory/health"
]

result = []

for service in services:
    result.append(check_service(service))

if all(result):
    print("DR FAILOVER TEST PASSED")
else:
    print("DR FAILOVER TEST FAILED")

然后把它接进:

代码语言:text
复制
CI/CD
+
监控
+
自动化测试

甚至可以每个月自动做一次:

代码语言:text
复制
创建灾备环境
      ↓
恢复数据
      ↓
启动应用
      ↓
执行业务测试
      ↓
生成报告
      ↓
销毁临时环境

这时候你的灾备就开始从:

“文档上的预案”

变成:

“可以重复执行的工程能力”。


十二、RPO/RTO 不是越低越好

这里也容易出现一个误区。

有人觉得:

代码语言:text
复制
RPO = 0
RTO = 0

最好。

理论上确实非常美。

现实中:

贵得离谱。

因为:

代码语言:text
复制
RPO 越低
↓
复制越实时
↓
网络要求越高
↓
存储成本越高
↓
架构复杂度越高

RTO 越低也是一样:

代码语言:text
复制
RTO 24小时
    ↓
备份恢复

RTO 1小时
    ↓
热备/自动化恢复

RTO 几分钟
    ↓
多活/快速切换

所以真正合理的策略不是:

“RPO/RTO 越低越牛。”

而是:

“业务价值决定 RPO/RTO,RPO/RTO 决定灾备投入。”


十三、我更推荐企业做一张“灾备等级表”

例如:

业务

RPO

RTO

灾备策略

内部报表

24h

24h

每日备份

普通业务系统

1h

4h

异地备份

核心订单

15min

1h

异步复制

核心交易

<5min

<30min

跨区域热备

极核心系统

接近0

分钟级

多活/自动故障切换

这样做最大的好处是:

不烧冤枉钱。

不是所有系统都值得上“两地三中心”。

一个内部 OA,非要搞:

代码语言:text
复制
三地五中心
+
多活
+
实时复制
+
自动故障切换

最后可能不是系统挂了。

是预算先挂了。


十四、最后聊聊我对“备份”的一个理解

以前我觉得:

运维的核心能力之一,是把系统稳定地运行起来。

后来慢慢发现,不完全是。

真正成熟的运维体系应该考虑:

代码语言:text
复制
系统正常
   ↓
系统异常
   ↓
故障发现
   ↓
故障隔离
   ↓
故障恢复
   ↓
数据恢复
   ↓
业务恢复
   ↓
复盘
   ↓
避免再次发生

所以:

备份不是终点。

恢复也不是终点。

真正的终点是:

哪怕整个 Region 都没了,我依然知道下一步该干什么,而且能够把业务重新跑起来。

这才是灾备真正的价值。

如果让我给一套生产环境备份体系提炼成一句话,我会这么设计:

代码语言:text
复制
3-2-1-1-0
+
明确 RPO/RTO
+
跨区域备份
+
自动化恢复
+
定期恢复演练
+
业务级验证

最后尤其是那个 0

它代表:

0 个未验证的备份错误。

因为真正发生事故的时候,没人会关心你的备份任务昨天是不是显示绿色。

大家只会问一句:

“现在能不能把系统救回来?”

而一个成熟的运维团队,应该能够很平静地回答:

“能。我们上个月刚演练过,而且恢复时间和数据丢失量,都在目标范围内。”

我觉得,这句话可能才是运维人员面对生产事故时,最有底气的一句话。

——Echo_Wish

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 数据备份做得再勤快,没做过这件事,真出事还是得抓瞎
    • 一、先搞明白:RPO 和 RTO 到底是什么?
      • RPO:最多允许丢多少数据?
    • 二、RTO 更现实:多久能恢复业务?
  • 三、备份策略其实经历了三个阶段
    • 第一阶段:能备份就行
  • 四、第二阶段:开始考虑 RPO/RTO
  • 五、第三阶段:真正开始考虑“跨区域”
  • 六、但是有个非常残酷的问题:你确定真的能恢复吗?
  • 七、所以真正的灾备,应该备份这五类东西
    • 1. 数据
    • 2. 配置
    • 3. 基础设施
  • 八、跨区域恢复最重要的,不是“备份”,而是“演练”
  • 九、一次完整的跨区域恢复演练应该怎么做?
    • 第一步:宣布灾难
    • 第二步:确认 RPO
    • 第三步:启动 Region B
  • 十、数据库恢复之后,千万别马上宣布“恢复成功”
  • 十一、甚至可以把灾备演练自动化
  • 十二、RPO/RTO 不是越低越好
  • 十三、我更推荐企业做一张“灾备等级表”
  • 十四、最后聊聊我对“备份”的一个理解
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档