Language:Chinese VersionEnglish Version

每位开发者都曾经历过备份策略在纸上看起来很完善,直到需要它工作时却出问题的窘境。那个因为没有人测试增量链而只能从一周前的转储中恢复的数据库。那个实际上在上游同步删除操作的文件备份,导致勒索软件攻击同时摧毁了源数据和备份。那个已经两年没人检查访问凭证的存储桶中的异地副本。备份策略不是一项勾选框活动——它是一个具有可测量属性的系统,而大多数团队实际上并没有测量过自己的备份系统。3-2-1规则为你提供了一个清晰思考你所拥有和所缺内容的框架,但规则本身并不足够。你还需要理解为什么良好的备份实现会在实践中失败,以及构建能够在真实条件下经受住考验的系统需要什么。

3-2-1规则:它的真正含义

3-2-1规则很简单:保留三份数据副本,存储在两种不同类型的存储介质上,其中一份副本异地存储。这个表述自胶片摄影时代就已存在,后来被适应到数字基础设施中,它之所以能够存活下来,是因为其背后的逻辑是合理的。三份副本意味着需要同时发生两次故障才会导致数据丢失——前提是这些副本真正是独立的。两种介质类型可以防止特定介质的故障模式:存储阵列控制器故障导致所有连接的卷损坏,但不会影响你的磁带归档。一份异地副本意味着主场所发生的物理灾难(火灾、洪水、盗窃)不会让一切都结束。

该规则的不足之处在于它没有提及恢复时间、恢复点或恢复可靠性。你可以完美地满足3-2-1要求,但仍然发现自己无法在合理的时间内恢复生产,因为没有人测试过恢复过程、加密密钥丢失,或者备份代理在八周前就已静默停止运行。该规则描述的是一种拓扑结构。你实际需要的是拓扑结构加上经过测试的程序加上证明程序已运行的监控。

思考这个问题的更完整方式:3-2-1是最基本的结构。恢复点目标(RPO)——你可以承受丢失多少数据——和恢复时间目标(RTO)——恢复可以在多长时间内完成而不会成为业务问题——是你的备份系统需要满足的属性。从负责应用程序业务方面的人员那里获取这些数字,即使那个人就是你自己。然后根据这些数字反向设计,而不是根据你首先安装的任何备份工具向前设计。

为什么大多数备份策略在实践中失败

故障模式具有足够的可预测性,你可以在灾难发生前进行审计。最危险的是未经测试的恢复。能够成功写入文件的备份软件与能够生成可恢复文件的备份软件并非同一回事。损坏的归档文件、不完整的事务日志、缺失的依赖项,以及备份时间与恢复时间之间的配置漂移,这些都是真实存在的问题。如果你从未实际从备份恢复到暂存环境并验证应用程序是否正常运行,你就不知道你的备份是否有效。你只有强有力的间接证据表明它们可能有效,但这并不是一回事。

第二种故障模式是缺少自动化。手动备份流程——即使是设计良好的流程——随着负责它的人变得忙碌、更换角色或离开团队而会随时间退化。依赖人类记忆的备份不是真正的备份,它们只是意图。通过 cron 或专用作业调度器实现的自动化不是可选的,而是基本要求。而没有监控的自动化几乎比没有好不了多少:三周前的凌晨2点,你的 cron 作业静默失败,意味着你过去三周一直在没有备份的情况下运行,同时还以为自己有备份。

第三种故障模式是备份与同步的混淆。云存储同步工具——rsync、rclone 的同步模式、Dropbox,甚至是 AWS S3 复制——都会双向传播更改或从源到目标传播更改,且没有保留功能。如果你删除了一个文件,删除操作也会被复制。如果勒索软件加密了你的源文件,加密后的文件会覆盖你的副本。同步不是备份。备份需要保留功能:能够从过去的某个时间点恢复,而不仅仅是当前状态的副本。

第四种是未经测试的加密密钥存储。加密备份在除一种情况外的所有威胁场景中都优于未加密备份:即在恢复时密钥无法访问的情况。仅存储在被备份的服务器上、存储在凭据已丢失的同一密钥管理器中,或存储在无人能够访问的电子邮件中的密钥,代表了一种不同于数据丢失但同样最终失败的故障类别。

数据库备份:为 PostgreSQL 和 MySQL 正确执行

数据库不仅仅是文件。在不与数据库引擎协调的情况下对活动数据库进行文件系统级别的快照,会产生不一致的副本——从技术上讲,这个副本可能包含所有字节,但不代表数据库实际处于的任何时间点。不要单独使用 rsync 或文件系统快照来备份数据库文件,除非你完全理解你的引擎所需的协调机制。

PostgreSQL:pg_dump 加 WAL 归档

pg_dump是对单个 PostgreSQL 数据库进行逻辑备份的正确工具。它生成的备份在备份开始时点是一致的,不依赖于其他表的任何锁,并且可以在不同 PostgreSQL 版本间移植。对于包括角色和表空间配置的完整集群备份,请使用 pg_dumpall。这两个工具都包含在任何 PostgreSQL 安装中,并生成 pg_restore 可以可靠重建的输出。

pg_dump 的局限性在于 RPO(恢复点目标)。如果您每晚运行备份,而数据库在下午5点发生故障,您将丢失一整天的数据写入。对于可以接受这种情况的工作负载,使用 gzip 压缩的每晚 pg_dump 并异地发送可以满足基本需求。对于任何需要以分钟而非小时为单位衡量 RPO 的情况,请添加预写日志(WAL)归档。

WAL 归档按顺序捕获每个数据库更改。结合基础备份,它可以让您恢复到任何时间点——而不仅仅是最后一次备份。配置很简单:在 postgresql.conf 中设置 archive_mode = onarchive_command,将 WAL 段复制到备份目的地的命令。像 pgBackRest 和 Barman 这样的工具将此包装成一个完整的备份管理解决方案,具有并行性、保留管理和恢复编排功能,比手动编写的脚本可靠得多。

MySQL: mysqldump 加二进制日志备份

MySQL 中相当于 pg_dump 的是带有 --single-transaction 标志的 mysqldump,它使用 InnoDB 的事务一致性进行非阻塞的一致性备份。包含 --master-data=2 以记录备份时的二进制日志位置——这是您需要应用后续二进制日志进行时间点恢复的坐标。没有它,您拥有一个一致的快照,但无法重放增量更改。

MySQL 的二进制日志扮演与 PostgreSQL 的 WAL 相同的角色:它们按顺序记录每个数据修改语句。启用 log_bin 并归档二进制日志后,您可以通过重放相关的二进制日志段来恢复到最后一次完整备份后的任何时间点。mysqlbinlog 工具可以处理这个问题,但在压力下正确操作的复杂性很大。对于生产环境 MySQL,考虑使用 Percona XtraBackup 进行物理备份(对大型数据库更快,开销更低)并结合二进制日志归档,或使用透明处理此问题的托管服务。

文件系统备份:restic、BorgBackup 和 rsync

对于应用程序文件、配置和资源,大多数小型团队在现代选择上会在 restic 和 BorgBackup 之间抉择。两者都支持去重(因此您不会在快照中重复存储相同的块)、加密和高效的增量备份。两者都得到积极维护,并支持广泛的存储后端。

Restic 的主要优势在于简单性和后端灵活性。单个二进制文件、直观的命令以及对 S3、Backblaze B2、SFTP 和本地存储的原生支持,使其能够快速投入使用。Restic 的去重是基于内容寻址的块级别,这意味着它处理文件重命名和移动的效率高于基于块的工具。恢复体验很简洁:restic restore 即可工作,并且仓库格式文档充分,以至于该项目已发布了无需 restic 二进制文件本身即可使用的恢复工具。

BorgBackup (Borg) 在处理大型仓库时更快,使用略微不同的压缩和去重方法,对某些工作负载可能更高效,并且拥有成熟的生态系统,包括 BorgBase(一个专为 Borg 仓库设计的主机存储服务)。其主要缺点是 Borg 仓库格式可移植性较差——您需要兼容的 Borg 版本才能读取它,这通常不是问题,但值得了解。

普通的 rsync 值得一提,因为它仍然是大多数人已经拥有并理解的工具。对于简单情况——将目录树同步到远程服务器——使用 --archive --delete 的 rsync 可以正常工作。对于需要版本控制和保留策略的备份用例,您需要使用带有硬链接快照模式的 rsync(类似 time-machine 风格),或者应该使用 restic 或 Borg。快照模式是:将文件同步到带日期的目录,将未更改的文件硬链接到前一个快照。这为您提供了一个可浏览的历史记录,其中每个快照看起来都是完整副本,但只存储新的或已更改的数据。像 rsnapshot 这样的工具可以自动化此模式。

云备份目标:使用什么以及实际成本

云对象存储用于备份的经济性已经显著改善。在已经稳定到 2025 年并延续到 2026 年的价格下,对于任何生产系统来说,不拥有异地云备份的成本论点都难以成立。

对于纯粹优化存储成本的备份工作负载,Backblaze B2 是最明确的选择。每月每 terabyte 约 6 美元,通过 Cloudflare CDN 合作伙伴提供免费下载出站流量,以及合理的 API 调用定价,B2 是满足 3-2-1 备份策略中”云端一份”要求的最低成本选项。Restic 和 Borg 都原生支持 B2。唯一需要注意的是,B2 是一家比 AWS 或 Google 小的公司,如果您需要耐用性保证和服务等级协议承诺的绝对最高水平,这一点就很重要。

Wasabi 的定价约为每月每 TB 7 美元,并提供免费的数据出口(但要求每个对象最少存储 90 天——存储您计划长期保留的数据)。它与 S3 兼容,这意味着任何支持 S3 的工具都可以使用它,并且它拥有多个地理位置。对于已经使用 S3 兼容工具且希望在不迁移到 B2 的情况下节省 AWS 成本的团队来说,Wasabi 是自然的选择。

AWS S3 Glacier 和 Glacier Deep Archive 的价格点分别约为每月每 TB 4 美元和 1 美元,但它们的检索成本和延迟使它们特别适合归档用例,即您希望永远不检索但需要保持合规性或长期保留数据的情况。对于您期望每月测试恢复且可能需要紧急恢复的备份,标准 S3(或 S3 Intelligent-Tiering)比 Glacier 更合适。只有在检索确实罕见且可以接受数小时的检索延迟时,经济上才 Glacier 更有优势。

如果您已经在运行 AWS 基础设施,那么每月每 TB 约 12.50 美元的 S3 Standard-IA(不频繁访问)是一个合理的中间选择——价格高于 B2 或 Wasabi,但操作上可以保持在您现有的 AWS 账户和 IAM 模型内,更为简便。

备份自动化与监控

一个未经监控运行的备份作业不能可靠地称为备份作业。在小规模场景下有效的设置是使用 cron 进行调度,加上一个”死亡开关”服务进行监控。Healthchecks.io 是这个领域的标准工具:每个备份作业在成功完成时会向一个项目特定的 URL 发送 HTTP ping。如果在预期时间内没有收到 ping,Healthchecks.io 会向您发送警报。免费版涵盖了大多数小型团队的使用场景,提供十次检查和电子邮件通知。

这个模式很简单。备份脚本以以下内容结束:

#!/bin/bash
set -e

# 运行备份
restic backup /var/www /etc /home 
  --repo s3:s3.wasabisys.com/my-backup-bucket 
  --password-file /etc/restic-password

# 根据保留策略删除旧快照
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

# 标记成功完成
curl -fsS --retry 3 https://hc-ping.com/your-check-uuid > /dev/null

开头的 set -e 意味着任何命令失败都会立即退出脚本,因此如果备份或修剪步骤失败,ping URL 永远不会被调用。这是正确的行为:您希望监控服务注意到缺少成功的 ping,而不是在失败前收到一个 ping。在 curl 调用中添加 --retry 3 可以处理临时网络问题,而不会掩盖真实的备份失败。

对于 PostgreSQL 备份自动化,同样的模式适用:将你的 pg_dump 或 pgBackRest 配置块包装在脚本中,在末尾添加健康检查 ping,使用 cron 安排计划,并验证检查按预期触发。在前几次计划运行后检查 healthchecks.io 仪表板,确认时间预期与现实匹配。

加密:静态传输和传输中

发送到云提供商或任何您不完全控制的远程存储的备份数据应在离开您的基础设施之前进行加密。这并非不信任特定的云提供商——而是关于存储凭证被泄露、提供商员工、法律取证以及您的备份数据只能由您读取这一普遍原则。

Restic 和 BorgBackup 都在写入任何后端之前加密存储库内容。加密密钥(或密码短语)永远不会离开您的基础设施。存储在 Backblaze B2 上的 restic 存储库是加密 blob 的集合:存储提供商只能看到密文。这是正确的模型。依赖云提供商端加密(S3 术语中的 SSE)的工具可以保护您免受某些威胁,但不能防止提供商级别的访问或凭证泄露。

密钥管理是困难的部分。解密您的 restic 存储库的密码短语需要存储在某个位置:在恢复时可访问(包括主基础设施消失的灾难场景中),不仅存储在被备份的设备中,并且免受未授权访问。具有离线备份的密码管理器、物理安全位置中的物理文档,或具有足够耐用性的秘密管理服务都可以满足这一需求。明确记录密钥存储方法,并验证负责处理事件的任何人知道在哪里找到它。

对于传输中加密:restic 和 Borg 在连接到基于 HTTPS 的存储后端时都使用 TLS。对于 SFTP 目标,SSH 连接加密传输。主要风险区域是使用 rcloneaws s3 cp 或类似工具的自定义脚本—验证连接是否使用 HTTPS 且未禁用证书验证。

恢复测试:每月演练

如果您想了解备份系统是否有效,每月恢复演练不是可选的。演练不需要完全的生产切换—它需要验证恢复过程能否从备份数据生成一个可运行的应用程序,而不依赖于在真实灾难中可能不存在的系统。

针对网络应用的最低限度月度演练应包括:启动一个干净的虚拟机或容器,恢复最新的数据库备份,恢复最新的文件备份,运行应用程序启动序列,验证应用程序能正确响应测试请求,确认数据是最新的。记录这些操作所需的时间。这就是你实际的 RTO 下限——即使在理想条件下,恢复所需的最短时间。如果平静的演练需要四小时,那么在实际事故条件下应计划更长时间。

如果可能,请自动化演练。一个能够配置基础设施、从备份恢复、运行冒烟测试并报告结果的脚本,比日历提醒手动测试要可靠得多。它运行速度也更快,这意味着你可以每周而不是每月运行一次,而不会每次都消耗一天的工程时间。在每个主要的基础设施即代码生态系统中都存在支持这种自动化的工具。

当演练失败时——而且它确实会在某个时候失败——这正是系统正常工作的表现。你在受控环境中发现了漏洞,而不是在生产系统宕机的凌晨2点。将失败的演练视为备份计划最有价值的产出。

WordPress 备份 specifics

WordPress 有一个与其架构相关的特定备份问题:应用程序状态分布在文件系统(主题、插件、上传文件)和数据库(内容、设置、用户数据)之间,如果备份只捕获了其中一部分而没有在同一时间点捕获另一部分,就会导致恢复不一致。数据库中的插件版本与磁盘上的插件文件不匹配,或者数据库中引用的上传文件在文件系统中不存在,这些都是常见的恢复失败模式。

对于 WordPress 最干净的方法是协调一致地同时备份数据库和文件系统,或者接受从略微不同时间点的备份进行恢复需要手动协调。对于数据库,mysqldump 或类似 WP-CLI 的 db export 工具可以生成干净的逻辑导出。对于文件系统,备份 wp-content(主题、插件、上传文件)——你不需要备份 WordPress 核心文件,因为这些文件可以从 WordPress.org 重新生成。对于大多数 WordPress 站点来说,wp-content 备份加上具有匹配时间戳的数据库转储就是一个足够的恢复单元。

托管 WordPress 托管通常包含备份,但请验证保留期,验证你实际上可以下载备份文件(而不仅仅是在同一主机上进行原地恢复),并验证数据库备份是否包含在内,而不仅仅是文件备份。在需要之前测试将备份转移到不同主机的能力是一项你应该具备的实际功能。

何时值得为托管备份付费

RDS 自动快照、Supabase 的内置备份、PlanetScale 的时间点恢复以及其他托管数据库服务的等效功能都是具有真实价值主张的成熟产品。问题不在于它们相对于 DIY 是否定价过高——在规模扩大时通常确实如此——而在于运行自己的备份基础设施的运营成本是否超过了这个溢价。

RDS 自动快照默认开启,几乎不需要配置。它们在保留窗口内提供时间点恢复功能、自动存储管理,如果配置了还会进行跨区域复制。对于在 RDS 上运行生产应用的双人团队来说,价值主张非常强烈:备份系统由 AWS 维护,经过大规模持续测试,除了设置保留期和偶尔验证快照是否存在外,不需要任何工程关注。对于大多数工作负载,成本(大约是存储成本的 10-20% 开销)是值得的,特别是当替代方案是一个没有得到应有关注的自管理备份解决方案时。

反对仅使用托管备份的理由是单供应商依赖。如果您的 RDS 账户被入侵,区域级快照可能成为攻击者的目标。如果您的账户被暂停或存在计费争议,访问快照可能会中断。而且,如果您决定迁移,RDS 快照不能轻易用于恢复到不同的数据库引擎或自托管 Postgres 实例。为了合规、运营独立性或包含供应商故障的灾难场景,一个备用的平台外备份——即使只是每周将 pg_dump 导出到不同的云账户——也能显著改善您的处境。

小型团队的灾难恢复规划

灾难恢复计划是一份文件,在发生事故时,当熟悉系统的人员无法参与、处于压力状态或两者兼而有之的情况下,它能回答特定问题。它不需要五十页那么长。它需要准确、可查找,并且可以被了解基础设施类别但不了解您特定应用的人员使用。

小型团队的最小可行灾难恢复文件包括:需要恢复的内容及其优先顺序;备份存储位置和访问方式(包括凭据或密钥位置,存储在带外);每个关键系统的分步恢复程序,编写时假设读者具有通用能力但没有特定的机构知识;RTO 和 RPO 目标以及如何验证您已达到这些目标;以及依赖项的联系信息(云服务提供商、DNS 注册商、CDN、您的恢复所依赖的任何服务)。

请让文档作者以外的人员尝试仅使用文档和备份进行恢复测试,以此来测试文档。测试中暴露的差距是这次练习最有价值的产出。每当你的基础设施发生重大变化时,都要更新文档。一份在六个月前准确但早于重大基础设施变更的灾难恢复计划在灾难场景中会产生误导——这 arguably 比没有计划更糟糕,因为它会制造虚假的安全感。

备份策略中的 3-2-1 规则实际上不是一个你完成后就可以归档的部署任务。它是一个具有可测量属性的持续系统,你需要定期验证。三份副本、两种介质类型、一份异地存储是拓扑结构。经过测试的恢复、带有死亡开关监控的自动化作业、文档化的程序和定期的演练,这些才使得拓扑结构成为一个在需要时真正能工作的系统。

By Michael Sun

Founder and Editor-in-Chief of NovVista. Software engineer with hands-on experience in cloud infrastructure, full-stack development, and DevOps. Writes about AI tools, developer workflows, server architecture, and the practical side of technology. Based in China.

Leave a Reply

Your email address will not be published. Required fields are marked *

You missed