VPS 数据备份与恢复完整指南 2026

一台 VPS 会遇到的数据事故,翻来覆去就那几种:磁盘损坏、rm 或脚本手滑删错目录、系统升级翻车、被入侵后文件遭加密或篡改、商家跑路或机器被回收。它们发生的概率各不相同,但善后方式只有一种:把数据恢复回来。所以这篇文章不从工具讲起,而是从「出事的那一天」倒推——先定验收标准,再决定备什么、用什么备、备到什么程度,最后落到一套今晚就能配好的组合方案。
一、唯一的验收标准:恢复成功过,而不是文件存在
很多人的备份状态,准确描述是「有一堆备份文件」。文件存在,只能证明某个时刻有数据被复制走过,不能证明这些数据可用:归档可能早已损坏,加密仓库的密码可能找不到,导出文件可能是数据库写到一半的残片,恢复时还可能发现少备了某个关键目录。
判断一套备份方案是否成立,只看两个指标:
- RPO(最多能丢多少数据):事故发生在最不利的时刻,你要倒退回哪个时间点。每日备份意味着最坏丢 24 小时内新增的内容。
- RTO(多久能恢复业务):从发现事故到服务重新可用,中间要花多少时间。
个人站点通常不需要企业级规格:RPO 24 小时、RTO 一两个小时,多数人是能接受的。先把这两个数定下来,后面的频率、工具、保留周期才有依据。反过来也成立:从没真正恢复过一次的备份,在事故真正发生之前,只能算「可能有备份」。
二、先分清要备什么:三类数据,丢起来疼的程度完全不同
把一台 VPS 上的东西按恢复难度分成三类,它们的备份方法并不通用。
| 类别 | 典型内容 | 丢失后的实际代价 | 备份要点 |
|---|---|---|---|
| 配置 | /etc、站点 server 配置、systemd 单元、crontab、证书、.env 与各类令牌、SSH 密钥 | 体积最小,重建最耗时。当初为什么这么配、哪个端口对应哪个服务,全靠记忆复原 | 整体打包带走,频率可以低,但清单要全;改配置后顺手补一次 |
| 文件型数据 | 上传附件、图片、静态资源、代码、Docker 卷中的非数据库文件 | 体积大,大多是不可再生的用户资产,丢了就是丢了 | 增量同步的主场,关注变更量而非总量 |
| 数据库 | MySQL / PostgreSQL / SQLite / Redis 里的数据 | 文件「在」不等于数据「在」,处理方式不对,拷回来的目录根本启动不了 | 必须单独用逻辑导出处理,见第五节 |
还有第四类最容易漏:备份系统自身的东西——备份脚本、定时任务定义、仓库密码、对象存储的访问凭据。加密备份的密码若只存在这台机器上,机器没了,异地那份备份就只是一堆解不开的乱码。密码的另一份副本要放进密码管理器或离线保存,这是整套方案里成本为零、价值最高的一步。
三、方案选型:五种手段,各补一段短板
市面上的备份做法拆开看就五类。先看清每类的原理和短板,再谈组合。
| 方案 | 原理 | 成本 | 恢复粒度 | 适合承担的角色 | 主要短板 |
|---|---|---|---|---|---|
| 商家快照 | 控制台对整块磁盘做镜像,一键回滚到快照时刻 | 多数商家免费几次或按容量计费 | 整机 | 系统大改版、升级前的临时保险 | 通常不能导出;商家出问题时快照跟着一起没;回滚会把整台机器的状态一起退回 |
| rsync 镜像同步 | 文件级增量传输,把目录同步到另一处 | 只有存储成本 | 文件级,拷回即可用 | 数据目录的快速副本 | 没有版本历史和加密;带 --delete 时会把源端的误删、被加密一并同步过去 |
| rclone 同步到对象存储 | 把本地目录同步到 S3 兼容存储 | 对象存储费用很低 | 文件级 | 异地那一份的运输管道 | 本质是镜像语义,需要靠对象存储的版本控制功能补历史版本 |
| restic / Borg 仓库式备份 | 内容去重、加密、每次备份生成一个可回溯的快照 | 软件免费,存储按实际占用 | 文件或整目录,可挂载逐个文件取回 | 主力备份层:版本、加密、去重都在这一层解决 | 多一层工具与密码管理;恢复大量小文件时速度一般 |
| 数据库逻辑导出 | 用官方 dump 工具把数据导成 SQL 文件 | 几乎为零 | 库、表级 | 数据库的专用通道 | 大库导出和回导都慢;参数用不对会导出不一致的数据 |
结论很直接:没有任何一类能单独兜底。快照保整机但出不了商家,镜像同步快但没有历史,仓库式最完整但需要管密码,数据库还得走自己的通道。个人 VPS 的合理做法是把它们拼起来,各管一段。
四、一套可直接落地的组合方案
下面这套组合针对最常见的形态:一台 VPS,跑着一两个站点加若干自建服务。它由三件事构成:每日一次 restic 备份进本机仓库、同一份数据再送一份到异地仓库、数据库在打包前先做逻辑导出。
目录与分工
/data/backup/
├── repo-local/ # 本机 restic 仓库(尽量与系统盘分开)
├── db-dump/ # 数据库导出的中转目录,只留最近几天
└── scripts/ # 备份脚本本体,也纳入备份范围密码单独存放:/root/.restic-pass,权限设为 600,内容另在密码管理器里存一份。
备份脚本
#!/bin/bash
# 每日备份:数据库导出 -> 本机仓库 -> 异地仓库 -> 清理过期快照
set -euo pipefail
export RESTIC_PASSWORD_FILE=/root/.restic-pass
LOCAL_REPO=/data/backup/repo-local
REMOTE_REPO="s3:https://s3.example.com/bucket-for-vps-backup"
DUMP_DIR=/data/backup/db-dump
DAY=$(date +%F)
mkdir -p "$DUMP_DIR"
# 数据库先导出成文件,再和文件数据一起进仓库
mysqldump --single-transaction --routines --triggers myblog \
| gzip > "$DUMP_DIR/myblog-$DAY.sql.gz"
find "$DUMP_DIR" -name '*.sql.gz' -mtime +3 -delete
TARGETS="/etc /var/www /home /opt /root/scripts $DUMP_DIR"
# 本机仓库
restic -r "$LOCAL_REPO" backup $TARGETS \
--exclude-caches --exclude 'node_modules' --tag auto-daily
# 异地仓库:同一批目录再跑一次,数据量不大时这是最省心的异地方式
restic -r "$REMOTE_REPO" backup $TARGETS \
--exclude-caches --exclude 'node_modules' --tag auto-daily
# 两边的保留策略不同:本机偏短期,异地多留月度
restic -r "$LOCAL_REPO" forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
restic -r "$REMOTE_REPO" forget --keep-weekly 4 --keep-monthly 12 --prune几点说明:
- 异地仓库用的是对象存储的 S3 接口,凭据通过环境变量或 restic 的配置提供,细节按所用存储商的文档设置。数据量大到双份全量跑不动时,再考虑用 restic 的仓库间复制功能。
--exclude-caches和排除node_modules这类目录很重要:它们可再生、体积大、变化频繁,不排除的话,每日增量会被垃圾撑满。- 仓库目录本身不要出现在备份目标里,否则备份会把自己越备越大。
保留策略为什么这样定
7 日 + 4 周 + 6 月 不是随手写的数字。每日留一周,覆盖「删错东西过了几天才发现」的常见情况;每周留一个月,覆盖月底对账、周期性任务出问题的时间窗;每月留半年,应对慢性污染——比如入侵者潜伏了几周才动手,或者某个 bug 在慢慢写坏数据,这时你需要回到很久以前的干净版本。异地那份存储便宜,把月度拉长到 12 份,成本几乎不变,安全边际明显不同。
定时与盯梢
# 每天凌晨 3:30 执行,输出全部留档
30 3 * * * /root/scripts/backup.sh >> /var/log/vps-backup.log 2>&1定时任务只解决「自动跑」,不解决「跑挂了没人知道」。脚本用了 set -e,任何一步失败都会中断退出,但退出本身是静默的。务实的做法:每周固定扫一眼日志尾巴;或者在脚本末尾加一段失败通知(邮件、聊天机器人 webhook 都行),让失败主动找你,而不是等事故日才发现备份三个月前就停了。
五、数据库单独处理:文件在,数据未必在
新手最常见的误判,是把数据库的数据目录(比如 /var/lib/mysql)当普通目录打包。运行中的数据库有相当一部分最新数据还在内存里,另一些写在事务日志中(InnoDB 的 redo log、PostgreSQL 的 WAL)。在服务运行状态下直接复制数据目录,得到的是某个不完整瞬间的碎片:运气好,数据库拒绝启动;运气不好,能启动但数据悄悄不一致。停机冷拷贝只适合有维护窗口的场合。
正确通道是逻辑导出,让数据库自己输出一份一致的数据:
- MySQL / MariaDB:
mysqldump加--single-transaction,它会在一个事务快照内导出 InnoDB 表,不锁表、不停服务。上文脚本用的就是这个参数。 - PostgreSQL:
pg_dump基于 MVCC,导出的天然是一致快照,不需要额外参数;恢复用psql或pg_restore导回。 - SQLite:是个例外,但别用文件复制偷懒。写入进行时直接
cp可能拷到写一半的状态,WAL 模式下还要连同-wal文件一起考虑。用它自带的.backup命令做在线备份,得到的是完整一致的单文件。 - Redis:拷走 RDB 文件是常见做法,但要清楚 RDB 只是最近一次持久化时刻的状态;开了 AOF 的实例以 AOF 为准,两者别混。
Docker 里的数据库同样适用以上规则:通过 docker exec 调用容器内的 dump 工具导出,或者把宿主机的导出目录挂载进去落盘。把数据卷目录整个打包,等于又回到「拷数据目录」的老问题上,只是外面多了一层容器。
只有当数据库大到逻辑导出耗时不可接受(通常是几十 GB 往上),才需要考虑 XtraBackup、pgBackRest 这类物理备份工具。小站阶段提前上这些,只会增加维护负担。
六、恢复演练:半年一次,一次半小时
备份方案配好之后,还差最后一道验收:在一台临时机器上,把数据真的恢复出来一次。
- 新开一台最低配的临时 VPS,或者用本地虚拟机。不要在生产机上练,演练的全部意义就在隔离。
- 从异地仓库(不是本机仓库)拉取最近一份快照,还原到临时目录,检查关键文件是否齐全、权限是否正确。
- 把数据库导出文件导入临时实例,不要只看导入有没有报错:随机抽两三张核心表,查一下总行数和最新一条记录的时间,和生产库对得上才算通过。
- 在临时机上把服务跑起来,本地改 hosts 指向它,打开首页和一两个关键页面点一遍。
- 记下这次恢复总共花了多久、卡在哪一步。这就是你的真实 RTO;卡点写进脚本旁边的说明文件,下次先修它。
- 销毁临时机器,演练结束。
第一次演练大概率会翻车:密码不在手边、某个目录根本没备、恢复顺序不对导致服务起不来。这些问题在演练里暴露,成本是半小时;在真实事故里暴露,成本可能是全部数据。半年一次的频率,是「记得住流程」和「不折腾」之间的折中。
七、常见翻车清单
| 翻车姿势 | 为什么致命 | 正确做法 |
|---|---|---|
| 备份只放在同一台机器、同一块盘上 | 盘损坏、机器被封、商家跑路时,数据和备份一起消失 | 至少一份异地,且与生产不在同一家服务商 |
| 只有镜像同步,没有历史版本 | 源端误删或被勒索软件加密后,下一次同步会把破坏同步到备份端 | 镜像之外必须有一层带版本历史的备份;对象存储记得打开版本控制 |
| 加密密码只存在服务器上 | 机器丢失即备份全废;或者密码和仓库被一起打包窃走 | 密码进密码管理器,并留一份离线副本 |
| 数据库只打包了数据目录 | 拷回的是不一致碎片,可能无法启动或数据错乱 | 一律走逻辑导出,见第五节 |
| 定时任务静默失败 | 脚本报错、环境变量缺失,备份停跑数月无人知晓 | 留日志、定期检查,或给失败加通知 |
| 仓库建在被备份的目录里 | 每次备份把上次的仓库也备进去,体积滚雪球 | 规划目录时让仓库与备份目标互不包含 |
| 配好之后再没碰过 | 第一次「使用」备份就是事故当天,所有问题集中爆发 | 每半年做一次恢复演练,见第六节 |
FAQ
每天的备份会占多少空间? 仓库式工具会做去重,实际占用取决于每天的真实变更量,而不是数据总量。内容型站点常见的量级是:首次全量几个 GB,之后每日增量只有几 MB 到几十 MB。想心里有数,跑满一周后对比一下仓库体积的变化即可。
商家快照能代替文件备份吗? 不能完全代替。快照回滚是整机一起退回,系统状态、其他服务的数据都会跟着回退,而且快照一般导不出来、离不开这家商家。它最合适的定位,是大版本升级或批量改配置之前的一道临时保险,长期备份仍要靠文件级方案。
备份频率应该定多高? 由你能接受丢多少数据决定。内容更新不频繁的站点,每日一次是合理下限;有用户注册、订单这类实时写入的业务,数据库需要更密的导出,或者在日备份之外加一层日志归档,把恢复点细化到小时甚至分钟级。
备份真的有必要加密吗? 只要备份会离开这台机器,就默认加密。对象存储自带的服务端加密是第二层,它防的是存储侧的问题,替代不了客户端加密;restic、Borg 这类工具的加密是内置的,开起来没有额外成本。
小站有必要搞这么全吗? 可以先上最小版:商家自动快照、一份异地 restic 仓库、数据库每日逻辑导出,三件事一晚上配完,之后全自动。本文的选型对照和保留策略,就是为这个最小版准备的;等数据长起来,再按同一套思路加密度和保留期即可。
写在最后
备份这件事,配置只占三成,剩下七成在于它是否被验证过。一套从没恢复过的豪华方案,不如一套每半年演练一次的朴素方案。今晚就可以动手:先把数据库导出和第一份异地仓库跑起来,其余部分再慢慢补齐。
延伸阅读:备份之外,系统优化设置指南 讲这台机器的性能与基础调优,Fail2ban 防爆破配置 处理 SSH 攻击面——一个减少出事概率,一个保证出事后有路可退。
延伸阅读
免责声明
本文仅供技术交流和学习参考。涉及第三方服务的链接可能包含 sponsored 标记,请自行核实服务条款、价格和可用性,并遵守当地法律法规。