一、美国VPS的备份到底在防什么

备份方案的设计必须先明确威胁模型,否则很容易花大力气备份了不该防的东西。
在美国 VPS 上,真正会导致数据丢失的来源大致有五类。
第一类,误操作。 手滑删错了目录,误跑了一条 rm -rf,配置改错了导致服务起不来然后覆盖了原文件。这类事故占实际事故的大多数,而且它们全部可以靠版本化的备份在几分钟内回滚。关键点是:要能恢复到"某一个具体时间点",而不只是"最近一次备份"。如果你是每小时备份一次,最坏情况要损失一小时的数据。
第二类,磁盘层面的故障。 宿主机硬盘损坏、RAID 阵列降级、云平台的底层存储出现坏块。这类故障的特征是整块盘不可读,本机上的任何备份(包括本机快照)如果也存在同一块盘上,会一起消失。
第三类,机房级事故。 机房断电、空调故障导致大规模宕机、网络配置错误导致整台机器从网络上消失。这是最需要"异地副本"来防的一类。
第四类,账号层面的问题。 密码泄露、SSH 密钥被盗、被勒索软件加密全部文件。勒索软件是特殊的一类:如果你的备份目录在同一个文件系统里且权限相同,加密程序会连备份一起加密。
第五类,商家侧的变更。 商家升级宿主机、迁移你的实例、更换硬盘类型、调整网络策略。这类事情通常会提前通知,但通知到了不等于你的数据没受影响。
对应这五类,备份方案要回答的问题分别是:能不能回滚到任意时间点、数据是否离开了这台机器、有没有一份攻击者够不着的副本、变更前有没有留档。
二、快照、镜像、文件备份、异地副本的区别

这四个词经常被混用,但它们能防的东西完全不同。
快照(Snapshot) 是存储层面的一致性时间点记录。它记录的是"此刻这块盘长什么样",恢复时整盘回滚,通常几分钟到几十分钟。它的特点是快、占用空间小(首次全量加增量)、恢复简单。缺点是它躺在同一台机器上——机器坏了、商家迁移了、账号被封了,快照一起没。它也不是文件级的:你不能从快照里单独取出一个文件。
镜像(Image) 是整机的模板化封装,可以用来创建新机器或重装系统。它偏向"复制一台新机器"的用途,不是"恢复我的数据"。
文件级备份 记录的是具体文件的某个版本,通常带版本历史。优点是可以精确取回任意文件、可以做增量、可以跨机器传输、可以选择性恢复。缺点是恢复时需要重新把文件放回正确位置,如果配置文件和应用版本不匹配,恢复完不一定能直接跑起来。
异地副本(Off-site copy) 指的是数据存放在另一台物理隔离的机器或对象存储上。它是唯一能防住第三类、第四类、第五类事故的方案。
它们的关系:快照和文件备份解决"误操作回滚",异地副本解决"物理层面的灾难"。成熟方案是两者叠加,而不是二选一。
需要特别强调一个被大量忽视的误区:商家控制台里的"快照"功能不是备份。它是同一台机器上的存储层快照,只防第一类(误操作)和部分第二类(逻辑层损坏)。防不住机房事故、商家迁移、账号封禁。
三、3-2-1 原则在小站上的落地

3-2-1 原则是:至少 3 份数据副本,存在至少 2 种不同的介质或存储位置,其中至少 1 份在异地(offsite)。
对个人和小团队站点,这个原则可以这样落地。
3 份副本:线上机器上的原始数据、机器本地的备份、异地的一份。三个都要是真实的独立副本,同一个磁盘上的多个快照只算 1 份。
2 种位置:本机 + 异地。只在两个不同目录下(比如 /data 和 /backup)不算两种位置,因为磁盘一坏全没。
1 份异地:可以是另一台 VPS、对象存储(兼容 S3 协议的那种)、或者 NAS。这一份是整套方案里最关键的一份,因为它是唯一能防住机房事故的。
按预算分档的落地方式:
最低档(约每月几美元):线上机器 + 机器上另一块盘的备份 + 一个对象存储桶。只备份数据库和配置文件,代码用 Git 托管不占备份空间。
标准档:加一台低配 VPS 当备份服务器,两台机器之间用加密同步。这样既有异地副本,成本也就是一台入门机器。
进阶档:用 restic 或 borg 做去重和加密,备份频率提高到每小时,甚至做不可变存储(对象存储的保留锁定功能),这样即使攻击者拿到了你的凭证也无法删除备份。
关于不可变存储值得多说一句。 勒索软件最难防的一环是"攻击者先删掉你的备份"。对象存储的合规保留策略(对象锁定、保留期)可以在服务端拒绝删除请求,即使你有完全权限的密钥也删不掉。这是目前对勒索软件最有效的防护手段之一。
3-2-1 原则的常见误用,有三个需要点破。
误用一:把三份副本放在同一台机器上。 有人的做法是在服务器上建三个目录,分别叫 backup1、backup2、backup3,然后每天往里各拷一份。这样在应对误操作时确实有效,但一旦遇到磁盘故障、商家重装、账号被封,三份一起消失。判定标准很简单:问自己一句"如果这台机器整个没了,这三份还在吗",答案是不能,就说明副本数量是假的。
误用二:把 Git 仓库当作备份。 Git 确实保存了代码的历史版本,但有三个致命缺口:一是 Git 通常不保存运行时产生的数据(上传的文件、日志、数据库);二是 .env、证书私钥这类文件经常被 .gitignore 排除,等于没备;三是远程仓库如果就在同一台机器上,那就还是本地副本。Git 是代码的版本控制,备份是数据的副本,两件事要分开做。
误用三:备份了但没验证过。 备份脚本每天打印"成功",日志看起来很绿,但从来没人在另一台机器上恢复过。这种备份在真正需要的时候可能完全不可用——数据库导出文件损坏、加密密码文件丢了、restic 仓库索引损坏,都是很常见的"备份看起来没问题但就是用不了"的场景。
四、rsync 备份:最朴素也最可靠的选择

rsync 是最经典的方案,优点是增量传输、保留权限和软链接、断点续传、几乎所有 Linux 都自带。
基础用法,把本地目录同步到本地备份目录:
rsync -avz --delete \
--exclude '.git/' \
--exclude 'node_modules/' \
--exclude '*.log' \
/var/www/ /backup/www/
几个关键参数的含义:
--delete 让备份目录跟源目录保持一致,源里删掉的文件在备份里也删掉。用这个参数之前一定要确认你的备份目标是独立目录而不是源目录的子目录,否则会把自己的备份删掉。
-z 启用压缩,传输量小很多,但会消耗 CPU。在带宽紧张而 CPU 空闲的机器上很有用。
各种 --exclude 排除规则能显著减小备份体积。缓存目录、日志、临时文件、依赖目录通常不需要备份。
跨机器同步的写法:
rsync -avz --delete --numeric-ids \
-e "ssh -p 22 -i /root/.ssh/backup_key" \
--exclude '.git/' \
/var/www/ backup@backupserver:/backup/www/
--numeric-ids 让权限按 UID/GID 数字传递而不是用户名,避免两台机器用户名不一致导致权限错乱。
用密钥免密执行(这是自动化备份的前提):
ssh-keygen -t ed25519 -f /root/.ssh/backup_key -N ""
ssh-copy-id -i /root/.ssh/backup_key.pub backup@backupserver
定时执行,把上面命令写进脚本,用 cron 每天凌晨跑:
0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
常见的 rsync 报错与处理:
报错一:rsync: link_stat "/path" failed: No such file or directory (2)。源路径不存在或者路径拼错。先用 ls -la 确认路径。这一条在变量拼接的脚本里最常见。
报错二:rsync: change_dir "/path" failed: No such file or directory (2)。目标路径不存在或者远程用户没权限写。确认远程账号对目标目录有写权限。
报错三:ssh: connect to host x.x.x.x port 22: Connection timed out。网络不通或防火墙拦了。检查两台机器之间的安全组规则和本地防火墙。
报错四:Permission denied (publickey)。密钥没配好或者 authorized_keys 权限不对。远程机上执行 chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys。
报错五:rsync error: some files/attrs were not transferred (code 23)。通常是权限不足导致某些文件读不到,或者目标目录满了。用 --exclude 排除掉不需要的文件,并检查目标盘的可用空间。
五、restic 与 borg:去重、加密、版本化

rsync 的问题是每次全量比较,文件多的时候慢,而且没有真正的版本历史——同步过去的旧版本被覆盖了。restic 和 borg 解决的就是这两点。
restic 的特点:加密备份、内容去重、快照式版本历史、支持 S3 兼容对象存储、支持加密密码。备份数据本身是加密的,泄露了备份文件也解不开。
初始化一个备份仓库:
restic -r s3:s3.amazonaws.com/my-bucket --password-file /root/.restic-pass init
备份命令:
restic -r s3:s3.amazonaws.com/my-bucket \
--password-file /root/.restic-pass \
backup /var/www /etc/nginx /etc/letsencrypt
查看历史快照:
restic -r s3:s3.amazonaws.com/my-bucket \
--password-file /root/.restic-pass \
snapshots
恢复某个快照:
restic -r s3:s3.amazonaws.com/my-bucket \
--password-file /root/.restic-pass \
restore latest --target /tmp/restore
查看某个文件的历史版本:
restic -r s3:s3.amazonaws.com/my-bucket \
--password-file /root/.restic-pass \
find /var/www --tag backup | tail -20
保留策略(自动清理老快照):
restic -r s3:s3.amazonaws.com/my-bucket \
--password-file /root/.restic-pass \
forget --keep-hourly 24 --keep-daily 14 --keep-weekly 8 --keep-monthly 12 --prune
--keep-hourly 24 保留最近 24 小时的每小时快照,--keep-daily 14 保留最近 14 天的每日快照,依此类推。这套参数组合的含义是:误操作发生后,你至少能回退到最近 24 小时内的任何一个小时点。
borg 的特点:压缩率通常优于 restic,适合 CPU 充裕的机器。支持挂载(mount)查看历史快照内容,这在排查"某个文件上周长什么样"时很方便。
borg init --encryption=repokey /mnt/backup/myrepo
borg create /mnt/backup/myrepo::{now} /var/www
borg list /mnt/backup/myrepo
borg extract /mnt/backup/myrepo::"归档名"
两者怎么选:机器 CPU 紧张或者备份目标在对象存储,选 restic;机器 CPU 有余量、希望能随时挂载查看历史,选 borg。
六、数据库备份:不能只备份文件

数据库是备份方案里最容易出错的部分,因为数据库的数据文件在运行时是处于不一致状态的——直接复制 .ibd 文件或 data/ 目录,拿回来的很可能是损坏的。
MySQL 的正确做法是用逻辑导出:
mysqldump -u root -p --single-transaction --quick --routines --triggers \
--default-character-set=utf8mb4 \
mydb | gzip > /backup/mysql/mydb-$(date +%F-%H%M).sql.gz
几个参数的意义:
--single-transaction 是 InnoDB 的一致性快照,导出期间不锁表。这是最重要的一个参数。
--quick 逐行读取而不是一次性载入内存,避免大库把内存撑爆。
--routines 和 --triggers 导出存储过程和触发器,少了这两个,恢复后应用逻辑会缺一块。
--default-character-set=utf8mb4 防止 emoji 变成问号。
PostgreSQL 用 pg_dump:
pg_dump -U postgres -Fc --file=/backup/pg/db-$(date +%F-%H%M).dump mydb
-Fc 是自定义格式,支持并行恢复。
关键点:导出的文件要立刻传走,不要留在本机。 一条完整的链路是"导出到临时目录 → 立刻同步到异地 → 删掉临时文件"。如果只做了第一步,数据丢了本机磁盘就没了。
一定要做一次恢复验证。 导出不等于能恢复。定期在另一台机器上跑一遍导入,确认文件不是空的、字符没有乱码、表结构完整。
binlog 也要备份。 如果你的数据库开启了 binlog,可以用它做基于时间点恢复(PITR),把误删数据的时间点附近的操作回滚掉:
mysqlbinlog --start-datetime="2026-11-14 10:00:00" \
--stop-datetime="2026-11-14 10:30:00" \
/var/lib/mysql/binlog.000042 > /tmp/undo.sql
七、异地存储选型与成本算账

异地存储有四个选项,成本和适用场景差别很大。
选项一:另一台低价 VPS 当备份机。 优势是可以完全控制、传输不产生流量费、没有 API 限制。劣势是要自己运维这台机器、硬盘故障风险同样存在、跨机房流量要算进 VPS 的月流量配额里。
选项二:对象存储(S3 兼容)。 优势是可靠性高、有保留锁定、按量计费、异地冗余由云厂商负责。劣势是按请求次数计费(备份频率高、文件多的场景请求数会很可观)、出网下载要收费、restic 这类工具能大幅减少请求数。
选项三:另一家云厂商的存储。 逻辑上与选项二相同,多一层"跨厂商"的隔离,防的是某一家厂商的故障。
选项四:免费或低价网盘同步。 适合纯文档类数据,不适合数据库备份和大量小文件——同步冲突、断点续传缺失、恢复速度都不可控。
成本怎么算:给你一个能直接套用的算法。
先估数据量。假设你的站点总数据量是 D GB,每周备份一次、保留 8 周。
如果用 rsync 同步,每次传的是全量(无去重),周流量约为 8 乘 D GB 乘 4(算上重传和版本占用)。以 D 等于 10 GB 的站点为例,周流量 320 GB,月流量约 1280 GB。
对照商品库里的真实配置看这个流量值意味着什么。LAX-MEDIUM 是年付 800 美元、折合每月 66.67 美元,8 核 8 GB 内存、160 GB 硬盘、10000 Mbps 端口、20000 GB 月流量,每 TB 流量单价 3.413 美元。1280 GB 流量在 20000 GB 配额里只占 6.4%,完全够用。
但如果你的备份要传到另一台机器上,那台机器也要跑流量。备份流量是双向的——这是很多人算漏的一笔账。
用 restic 或 borg 的去重后,实际传输量通常降到原始数据量的百分之十到三十。同样 10 GB 的站点、每天备份、保留 30 天版本的情况下,月流量大概在 10 GB 到 100 GB 之间,比 rsync 省一个数量级。这就是为什么严肃的备份方案都用去重工具。
硬盘容量也要算。 用 restic 的话,仓库初始大小约等于一次全量,之后每个版本的增量取决于数据变化量。如果每天只有 5% 的数据变化,30 天的版本历史大约需要 1.5 倍原始数据量的空间。用 borg 的话,由于压缩率更好,通常在 0.6 到 1 倍之间。
再算一笔常被漏掉的账:备份机器本身的流量配额。 如果备份目标是另一台 VPS,那台机器也要承担接收流量。参照商品库的真实配置:LAX-STARTER 是年付 200 美元、折合每月 16.67 美元,2 核 2 GB 内存、40 GB 硬盘、2000 Mbps 端口、5000 GB 月流量,每 TB 流量单价 3.413 美元。这个档位可以当备份机用,但 5000 GB 月流量对接收端是上限——备份流量要从这台机器的配额里扣,不是无限的。
同时要注意备份机的硬盘容量限制。40 GB 硬盘的备份机,只能装下原始数据量的两三倍(含去重和版本)。如果你要备份 100 GB 数据并保留 30 天版本,这台机器至少要 150 GB 硬盘。商品库里的 LAX-Storage-500G 是年付 400 美元、折合每月 33.33 美元,4 核 4 GB 内存、500 GB 硬盘、10000 Mbps 端口、10000 GB 月流量,每 GB 硬盘成本 0.067 美元——把它当备份机用,容量和流量都宽裕很多,成本是 STARTER 的两倍。
给你的选型结论:数据量在 20 GB 以内、每天备份一次,用 STARTER 级别当备份机就够;数据量在 100 GB 级别、要保留长期版本,选 Storage 系列;如果每天备份且要保留 30 天以上版本,直接上对象存储,避免备份机的流量配额成为瓶颈。
八、自动化:让备份在你不看它的时候也可靠

手动备份等于没有备份,因为你会忘记。但自动化会带来新的风险——脚本静默失败,你以为有备份其实没有。所以自动化必须配上失败告警。
一套完整的自动化方案由五部分组成。
第一部分:备份脚本。 核心要求是每次运行都留下日志,并且用退出码表示成功或失败。
#!/bin/bash
set -euo pipefail
LOG=/var/log/backup-$(date +%F).log
BACKUP_DIR=/backup
RESTIC_REPO=s3:s3.amazonaws.com/my-bucket
exec >> "$LOG" 2>&1
echo "=== 备份开始 $(date -Iseconds) ==="
# 1. 数据库导出
mysqldump -u root -p"$DB_PASS" --single-transaction --quick \
--routines --triggers --default-character-set=utf8mb4 \
mydb | gzip > "$BACKUP_DIR/db-$(date +%F-%H%M).sql.gz"
echo "数据库导出完成"
# 2. 配置文件与网站目录
restic -r "$RESTIC_REPO" --password-file /root/.restic-pass \
backup /var/www /etc/nginx /etc/letsencrypt /root/scripts
echo "文件备份完成"
# 3. 保留策略
restic -r "$RESTIC_REPO" --password-file /root/.restic-pass \
forget --keep-hourly 24 --keep-daily 14 --keep-weekly 8 --keep-monthly 12 --prune
echo "清理完成"
echo "=== 备份成功 $(date -Iseconds) ==="
第二部分:定时器。 用 cron 或 systemd timer。
# 每天凌晨 3 点 17 分执行(避开整点,减少与其他任务撞车)
17 3 * * * /usr/local/bin/backup.sh
用 systemd timer 更好,因为它有依赖关系和失败状态记录:
[Unit]
Description=Daily backup
[Timer]
OnCalendar=*-*-* 03:17:00
Persistent=true
[Install]
WantedBy=timers.target
Persistent=true 这一行很重要:机器在定时点关机时,开机后会补跑一次任务。
第三部分:失败告警。 这是最容易被省略但最重要的一环。常见做法是让脚本在失败时调用一个 webhook 发消息,或者把结果写入一个状态文件,再由另一个定时任务检查并告警。
# 在脚本末尾追加
if [ $? -ne 0 ]; then
curl -s -X POST "https://your-webhook-url" \
-d "message=备份失败 $(hostname) $(date -Iseconds)"
fi
第四部分:完整性校验。 备份文件本身可能损坏,而且要过很久才会被发现。restic 提供了校验命令:
restic -r s3:s3.amazonaws.com/my-bucket \
--password-file /root/.restic-pass \
check --read-data
check 验证仓库结构,check --read-data 还会把数据块全部读出来验证哈希,耗时较长但能发现数据损坏。建议每周跑一次带 --read-data 的完整校验。
第五部分:异地副本的独立性验证。 定期去异地存储上确认快照确实存在且可读,不要只信脚本的日志。脚本可能因为某个原因(比如环境变量没传进去)"成功"了但其实什么都没备份。
九、恢复演练:不做演练的备份不算备份

这是整篇文章里最该被执行的一节。备份的价值完全由恢复能力决定,而恢复能力只能靠演练获得。
演练的频率:每季度至少一次完整的灾难恢复演练,每个月至少一次抽样恢复。
完整演练的流程:
第一步,准备一台干净的机器。这台机器的配置要和原机器接近——如果原机器是 4 GB 内存而你在一台 1 GB 的机器上演练,恢复过程可能会因为内存不足而失败,那就没有验证到真实场景。
第二步,只用备份恢复。关键纪律:不要从原机器复制任何东西。 如果你在恢复过程中顺手从原机器拷了个配置文件,这个演练就失去意义了。
第三步,按顺序恢复:先系统与依赖(PHP 版本、Nginx、扩展),再网站文件,再数据库,最后配置。
第四步,跑验收检查:
# 检查网站文件是否完整
find /var/www -type f | wc -l
# 检查数据库能否正常导入
mysql -u root -p -e "SHOW TABLES;" mydb
# 检查关键接口是否响应
curl -s -o /dev/null -w "%{http_code}\n" https://your-site.com/
# 检查关键页面内容是否正确
curl -s https://your-site.com/ | head -50
第五步,测量恢复时间。记录从开始恢复到服务可用花了多久。这个数字决定了你真正出事故时的损失规模——如果恢复要 4 小时,那你的 SLA 里就应该写明这个数字,而不是假装能快速恢复。
第六步,记下所有卡住的地方。这些卡点就是下次演练要重点验证的,也是要提前写进文档的。
抽样恢复是每月做的轻量版本:随便挑一个最近三天的快照,只恢复其中一个文件或一个数据库表,确认备份里真的有这些内容、且能正常打开。这一步成本很低,但能提前发现"备份脚本一直在成功运行但其实备份了空文件"这类问题。
演练要记录什么:恢复耗时、遇到的报错、缺失的依赖、需要人工干预的步骤。这份记录本身就是最有价值的备份文档,因为它描述的是真实发生过的事,而不是设想。
按你的情况,下一步该看哪家
上面讲的是判断标准,但多数人最后还是想问一句「那我该买谁」。按你的实际情况对照下面几条,直接去看对应的机型页比继续比价更快:
- 只是开发测试、临时用:按小时或月付,用完就删,别买年付。看 spinservers 当前机型与价格
价格与库存以商家页面当日显示为准,下单前建议先确认退款窗口与是否支持按月付费。
十、常见问题

问题一:商家控制台的快照功能算不算备份? 算一种备份,但只防误操作和部分逻辑层故障。它在同一台机器上,防不住机房事故、商家迁移、账号被封。要有异地副本才算完整。
问题二:备份应该备份什么? 至少四类:网站代码和上传的文件、数据库、服务器配置(Web 服务配置、SSL 证书、计划任务、防火墙规则)、以及凭据文件。代码如果用 Git 管了就不用重复备份,但 .env 这类必须单独备。
问题三:rsync 和 restic 该选哪个? 数据量小、想要简单可读:rsync。要版本历史、去重、加密、传到对象存储:restic。
问题四:备份放在同一台机器的另一个目录可以吗? 不可以。磁盘故障、商家迁移、账号问题会同时带走两份。它只比不备份好一点。
问题五:多久备份一次合适? 看你能接受丢失多少数据。数据库每天至少一次,重要站点每 4 小时一次,用 restic 的 --keep-hourly 24 可以做到每小时一个版本。
问题六:怎么验证备份真的能用? 定期做恢复演练,在另一台机器上完整恢复一次。只看脚本日志说"成功"是不够的。
问题七:备份占用多少空间? 用 rsync 是原始数据的 1.5 到 2 倍(含版本和压缩后残留);用 restic 大约 1 到 1.5 倍(增量);用 borg 通常 0.6 到 1 倍。
问题八:备份会消耗多少流量? rsync 无去重时接近全量数据的倍数;restic/borg 因为去重通常降到原始数据的百分之十到三十。按每周或每天备份周期乘以数据量估算,再对照你的月流量配额。
问题九:备份脚本半夜失败了我怎么知道? 必须配告警。做法是脚本失败时调 webhook 推送,或者写状态文件加一个独立的检查任务。只靠 cron 的日志是不够的,你不会每天去翻日志。
问题十:误删了一个文件,多久能恢复? 取决于你的备份频率和保留策略。restic 配 --keep-hourly 24 的情况下,最近 24 小时内任意一小时点的版本都在,理论上可以恢复到那个小时点删文件之前的状态。
问题十一:迁移到新服务器时备份能直接用吗? 备份只存数据,不存环境。新机器上要重新装依赖(尤其是 PHP 和数据库的大版本),恢复完数据后要检查配置里的路径和版本依赖。
问题十二:服务器被商家强制重装或迁移了怎么办? 这正是必须有异地副本的原因。数据在另一台机器上,重装完系统按第九节的流程恢复即可。这也解释了为什么"备份放在自己机器上"和"备份放在别人机器上"是两个完全不同性质的事情。
问题十三:价格上备份方案大概要花多少? 商品库里的机型价格是实例本身的价格,备份所需的第二台机器或对象存储是额外支出。用最低档方案(一台入门 VPS 当备份机)时,成本就是另一台机器的月费;用对象存储时,成本按存储量和请求数计费,具体以服务商官网当日报价为准。

喜欢
高兴
鬼脸
呵呵
无聊
伤心