服务器入坑指北:增量备份的深度与恢复链长度

举报
Tulpartner 发表于 2026/11/13 09:12:18 2026/11/13
【摘要】 备份越攒越多,恢复越算越怕;不知道该留几层;真出事时才发现链断了一环。 在你动手调层数之前,先把三条前提看清:① 层数是取舍,不是越少越好——层数少=每份更大、占用多;层数多=恢复要读更多份、链路更长、断一环的风险更大;② 链是链式依赖:每一层都依赖它的前一层,缺一环,整条链就落不了地——所以"备份跑完了"不等于"链是完整的";③ 多数工具需要先装包或只适用于特定文件系统

备份越攒越多,恢复越算越怕;不知道该留几层;真出事时才发现链断了一环。
在你动手调层数之前,先把三条前提看清:① 层数是取舍,不是越少越好——层数少=每份更大、占用多;层数多=恢复要读更多份、链路更长、断一环的风险更大;② 链是链式依赖:每一层都依赖它的前一层,缺一环,整条链就落不了地——所以"备份跑完了"不等于"链是完整的";③ 多数工具需要先装包或只适用于特定文件系统(下面每条命令都带了它自己的前提)。
这篇给三段可直接粘贴的内容:数层与看链 → 算两式 → 抽验每环与恢复演练(最后一段含"别在生产上试"的有副作用动作)。取值用占位符,命令名与参数名照写。

恢复要读几份,由层数决定

恢复时需读的份数 ≈ 增量层数 + 1——因为要先落全量、再逐层往前推。
判据:先数清链里有几层,再谈恢复要多久——顺序反了会把"恢复很慢"误判成"盘太慢"。
几个名字先认全:数层用 find <备份根> -mindepth 1 -maxdepth 1 -type d(-mindepth 1 用来排除起点目录本身)或 restic snapshots;看实占用 du -sh <层目录>、看去向 du -shc <各层目录> 的合计;量耗时用 ps -o etime= -p <PID> 轮询或两次 date +%s 相减。工具名统一写法:rsync / tar / restic。

数层与看链块

find <备份根> -mindepth 1 -maxdepth 1 -type d   # 数层数:排除起点目录本身,一行一层
restic snapshots                              # 数层:列出快照份数(需先装 restic)
du -sh <层目录>                                # 每层实占(人类可读)——注意 -b 是表观字节数,二者不是一回事
du -sb <层目录>                                # 表观字节数:与实占不是一回事,容量那一路不要用它
du -shc <各层目录>                             # 各层合计:硬链接只算一次,容量的总数看这个
tar -tzf <归档>                                # 抽验某层内容:能列出内容即该层可读

判据:每一行的数都要认领它在算什么——find <备份根> -mindepth 1 -maxdepth 1 -type d 的行数是层数,du -sh <层目录> 是每层实占、du -shc <各层目录> 是去重后的合计,tar -tzf <归档> 只判该层可读不可读——它判不出"这一层是不是增量层"(增量信息在快照文件里,不在归档清单里)。

算两式

第一式:恢复份数 = 层数 + 1。
算一遍(数值为演示值):用上面那条带 -mindepth 1 的命令数出层数 6(若你用的是不带 -mindepth 1 的老写法 find <备份根> -maxdepth 1 -type d,行数会是 7——那是把起点目录本身也数进去了,要减掉 1,并说清减的就是它)⇒ 恢复份数 = 6 + 1 = 7(1 份全量 + 6 份增量)。读数口径与算例里的"6"必须对齐,否则读者数出 7 却按 6 算。
第二式:恢复耗时 ≈ (层数 + 1) × 单层耗时;存储占用 ≈ 去重后的总实占。
"单层耗时"要按层类型分别量:全量层与增量层的代价不同——层大小相差很大时不能共用一个数;下面那个 20 分钟只在各层大小相近时当平均值用。
接着算(同一组数往下走):单层耗时按 20 分钟(层大小相近时的平均值)⇒ 最坏恢复时长 ≈ (6 + 1) * 20 = 140(分钟,约 2.3 小时)。
存储占用这一路不能靠加法:用 du -shc <各层目录> 的合计——它会把硬链接只算一次。为什么不能逐层 du -sb 相加:① -b 给的是表观字节数,与实占不是一回事(稀疏文件上能差到"一个很大、一个为 0");② 用 --link-dest=DIR 造的层里,未变化的文件是从 DIR 硬链接过去的,逐层相加会把同一份数据重复计——实测能偏高到几倍。
"单层耗时"必须是量出来的,不能假设(它=读一份并应用的代价,不是"拷一份的时间"):

date +%s                                      # 通用测法:开始前记一次
ps -o etime= -p <PID>                          # 轮询该进程已运行时长取差值(ps 由 procps 提供)
date +%s                                      # 结束后再记一次;两次相减=秒数

判据:两个量一起摆出来才叫取舍——链条越长越省容量、越脆;把"省下的空间"与"多花的恢复时间"并列看。

层是怎么造出来的(工具不同,前提不同)

tar -g <快照文件> -czf <归档> <目录>            # 造一层增量:快照文件记住"上次到哪"
rsync -a --link-dest=<上一版目录> <源> <新版本目录>   # 硬链接式"层":每层看着完整、实际只存变化(rsync 未装则先装)
xfsdump -l <级别> -f <归档文件> <挂载点>         # 级别语义:0 是全量、更高级别只存自上次更低级别以来的变化(需先装 xfsdump,且仅适用于 XFS)
btrfs subvolume snapshot <源子卷> <目标子卷>     # 快照式"层"(同一子卷上的层之间共享块;需先装 btrfs-progs)

两种"层"的关键语义:

  • --link-dest=DIR:与 DIR 中未变化的文件建立硬链接,只传变化——所以每层看着完整、实际只存变化;
  • --listed-incremental=FILE:增量级别的记录处——删掉这个文件,链就断了;
  • -l level(xfsdump):0 是全量、N 是自上次更低级别以来的变化——级别用错会让下一次静默退化成全量:它只按"自上次更低级别以来的变化"计算,级别用得比之前更低,就会把大量内容重新包含进来,你以为在存增量、其实在存全量——这是最容易让人白备份的一条。

链是链式依赖,要抽验每一环

每一层都依赖它的前一层——所以:

tar -tzf <归档>                                # 归档能列出内容 ⇒ 该层可读
restic snapshots                              # 快照清单一行一个 ⇒ 缺哪一份一眼可见
zfs send -i <起始快照> <目标快照>                # 增量流:接收端必须按链补齐才能落地(需先装 OpenZFS;选项以 zfs send --help/手册现读为准)
zfs receive <数据集>                            # 接收落地:链上缺一环就收不了(选项以手册现读为准)

判据:抽验每一环可不可读(能列出内容/能列出快照/能收下流),而不是只看最后一份在不在——"备份跑完了但链不全"就是只看最后一份的后果;zfs receive <数据集> 收不下时的报错位置直接指出链上缺的是哪一环。

取舍:留几层

  • 按天数留:简单;代价是数据量大时层数暴涨;
  • 按层数留:层数固定;代价是覆盖的时间跨度不定;
  • 定期合成全量:把链缩短;代价是合成本身要跑一次、要额外空间。
    三条代价都要写出来。判据:先问"最坏情况下我要恢复到多久以前"——那决定层数下限;再拿第二式的恢复耗时与你的恢复目标比:恢复目标小于算出来的时长,就得插入新的全量把链缩短。

抽验每环与恢复演练块

恢复演练是有副作用的动作——在非生产上做,并记回滚点:

restic restore <快照ID> --target <目录>         # 恢复动作:实测"要读几份"的入口(需先装 restic)

判据:--target <目录> 指向非生产目录;演练前记下该目录的原状态(回滚依据);演练完把实际耗时与第二式的估算对照——对不上就先看单层耗时是不是量少了。

现象到动作的判定表

现象 结论 动作
恢复慢 先数层数,别先怪盘 用第一式数份数,再用第二式算时长
空间涨得快 层数太少 每份更大、占用多;评估是否加层
链断一环 链式依赖 抽验每一环,用 zfs receive <数据集> 的报错定位缺哪一环
不知道留几层 没有下限依据 先定"最坏要回到多久前",再比恢复耗时
备份跑完了但链不全 只看最后一份 每层都抽验(能列出内容/能列出快照/能收下流)

改完怎么验证:每项一条判据

  • 层数数得出(清单行数);
  • 两式都算得出(份数与时长);
  • 单层耗时是量过的(不是假设的);
  • 每环都抽验过;
  • 恢复演练有回滚说明,且不在生产上;
  • 装包与环境前提都带了。

这篇不解决什么

  • 讲备份窗口与业务窗口错峰的那篇管什么时候备、窗口够不够;本篇管"链有多少层、恢复要读几份"。判定入口:“窗口不够”→ 那篇;“恢复要多久”→ 本篇。
  • 讲稀疏文件与预分配的那篇管单份文件的实占;本篇管多份之间的依赖关系与恢复链长度。
  • 讲不可复现问题的观测代价取舍的那篇管观测代价;与本篇无重叠。

踩坑清单

  • 只看最后一份在不在:链断了也不知道。
  • 把"层数少"当成好:每份更大、占用更多。
  • 恢复慢先怪盘:其实是层数。
  • 算恢复耗时却假设单层代价:结论只是猜。
  • 在生产上做恢复演练:验证动作自己成了事故。
  • 引用 zfs 选项不加限定:那些选项字母以现读为准。
  • 忘了工具要先装或限特定文件系统:xfsdump 仅 XFS、btrfs-progs/OpenZFS/restic 都要先装。
  • 定期合成全量却没算它要的空间:把空间问题推给了下一次。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。