西西软件园多重安全检测下载网站、值得信赖的软件下载站!
软件
软件
文章
搜索

首页 → 业内动态 → 业内资讯 → btrfs 子卷快照原理:写时复制让备份只多花 3% 空间

btrfs 子卷快照原理:写时复制让备份只多花 3% 空间

相关软件相关文章发表评论 来源:本站整理时间:2026/11/5 5:25:36字体大小:A-A+

作者:xiix点击:0次评论:0次标签: btrfs 子卷快照 写时复制 数据备份 文件系统

  • 类型:备份还原大小:5.7M语言:中文 评分:10.0
  • 标签:
立即下载

去年有位客户找我,说要给他一台跑 WordPress 的 VPS 配备份,预算有限,别太贵。我先按老套路查了一下数据量:网站文件加数据库 dump,加起来 47G。他一听就乐了,说那每天备份一份,一个月存 30 份就是 1.4T,硬盘直接躺平。

我说不用这么贵,然后把盘做成了 btrfs。这事儿的关键不在于「快照是免费的」这句宣传语,而在于快照到底是怎么实现的btrfs 用的是写时复制,新快照并不拷贝数据块,而是和源子卷共享同一批块,等你真的改了哪个文件,才把那个块单独写出来。这就是为什么我给他做完之后,20 份快照加起来只多占了不到 3% 的空间。

如果你正在给服务器配备份,下面两家在存储硬件上的定位和这篇内容比较贴,可以先拿它们的配置单做参考:搬瓦工(RAID-10 SAS 硬盘阵列的低价 VPS,磁盘冗余做在底层,适合放快照多的备份盘)、EthernetServers(NVMe SSD 固态硬盘主机,快照恢复时读写快,机器位便宜)

数据中心磁盘阵列特写,btrfs 快照共享底层存储块

快照到底存了什么:三个概念先捋清楚

btrfs 里最容易搞混的是「卷(volume)」「子卷(subvolume)」「快照(snapshot)」这三个词。卷是整个文件系统,磁盘格式化成一个卷;子卷是卷里一个独立的、可单独挂载的命名空间,根目录本身就是一个子卷;快照则是某个子卷在某一时刻的只读副本,它在 btrfs 内部其实也是一个子卷,只是被标记成只读。

所以关键动作就两条:btrfs subvolume create 开一个新的子卷,btrfs subvolume snapshot 把某个子卷拍成只读快照。两者之间共享文件数据块,共享的部分是只读的任何一方写了,btrfs 才把那个块复制出来给写入方,这就是写时复制。

这里面有个反直觉的地方:写时复制带来的不是「快照更便宜」,而是「快照的空间占用取决于改动量,不取决于数据总量」。100G 的站点你天天改,20 份快照可能吃掉几 G;同一个站点一个月不动,20 份快照几乎不占额外空间。反过来,如果你把快照和源卷混着放,系统还没来得及共享块就先把空间吃光了这也是后面要讲的坑之一。

写时复制原理示意:快照与源卷共享数据块

实战:3 条命令给站点做一份可回滚的快照

先规划目录。别把整台机器的根目录当快照对象,那样系统日志、缓存、临时文件全被卷进来,噪音很大。我一般在盘上单独开一个子卷放站点数据,另一个放数据库导出:

sudo btrfs subvolume create /data/www
sudo btrfs subvolume create /data/db
sudo btrfs subvolume snapshot -r /data/www /data/snap/www_$(date +%F)

第三条里的 -r 一定要加,意思是递归地把子卷下嵌套的子卷也一起拍进去,并且生成的快照是只读的(read-only)。如果你忘了加 -r,嵌套子卷不会被包含,备份就是残的这一点我见过太多人踩。

拍完之后看一眼真实占用:

sudo btrfs filesystem usage /data
sudo btrfs filesystem du -s /data/snap/www_2026-11-01

第一个命令看整个文件系统的已用、已分配空间,第二个看某份快照「独占」多少空间。这个独占值才是你真正为这份快照付出的钱。如果一个快照独占 0,那就说明它一行数据都没改过。

工程师在服务器终端前执行 btrfs 快照命令

回滚:把站点换回昨天那一版

有了快照,回滚反而是三步的事。关键是先挂一份快照出来确认内容对不对,别上来就覆盖:

sudo btrfs subvolume snapshot /data/snap/www_2026-11-01 /data/tmp_check
sudo mount -o ro /dev/sdb2 /mnt/check && ls /mnt/check
sudo mv /data/www /data/www_broken && sudo mv /data/tmp_check /data/www

第一行把只读快照复制成一个可写的临时子卷(快照本身不能直接当数据目录用),第二行挂上去看内容,第三行才是真正的替换。第三行里的 mv 之所以写成两步而不是直接删,是因为老目录里可能还有没提交的东西,先改名保留着,确认新版本跑一天没问题再删。

删快照本身也有一套讲究,btrfs subvolume delete 会报错的情况很多,最常见的就是「目标子卷还有子快照」btrfs 不会自动级联删除,你得先把下层的快照按从新到旧的顺序删掉,或者用 btrfs delete subvolume 加 -R 参数递归。

btrfs 卷被复制成多个只读快照的分层结构

真正救命的操作:把快照送到另一台机器

本地快照只能防误删,防不了磁盘整个没。真要能抗故障,得用 btrfs send 和 btrfs receive 把快照增量同步到另一台机器上:

sudo btrfs send -p /data/snap/www_2026-11-01 | ssh [email protected] 'sudo btrfs receive /backup'

-p 是 parent,指明这是一份「上一份快照的后代」,对方机器上必须已经有那份父快照,btrfs 才知道只传差异块。第一次全量传不带 -p,之后每次都带,这是增量传输省流量的关键。我那次给客户搭的时候,100G 的站点第一次全量传了 40 分钟,后面每天的增量只跑 3 分钟不到,其中大部分时间还是花在数据库 dump 上。

顺便提醒一句,btrfs send 走 SSH 的时候别忘了加 -C 开启压缩,在带宽紧张的网络上能省不少事:

sudo btrfs send -p /data/snap/www_2026-11-02 | ssh -C [email protected] 'sudo btrfs receive /backup'

四个坑,我基本都替客户踩过

第一,快照和源卷混放,空间立刻翻倍。新子卷刚建好、还没来得及共享块的时候,系统得先给子卷分配一份元数据和数据块,这时候两边各自占一份。只要你按上面说的顺序先建子卷、先往里写数据、再拍快照共享才能生效。同理,一份快照刚拍出来就去大量改它,独占空间会迅速往上蹿。

第二,快照不是备份,是「同一个盘上的另一个引用」。磁盘挂了、文件系统损了,这份快照跟着一起没。很多人的第一个反应是「我天天拍快照,稳了」,其实还是得配 send/receive 或者至少定期 rsync 到异机。我见过客户把快照目录和网站放同一块盘上,然后整块盘挂掉,快照一个没剩。

第三,删子卷时空间没回来。如果你用的是 btrfs subvolume delete 而它失败了,空间不会释放;而且删掉快照之后,数据块可能还被别的东西引用着,不一定立刻回收。这时候要跑 btrfs filesystem balance(新版是 balance start)重新分配块,跑完再看 filesystem usage,通常就回来了。

第四,快照会放大写入放大。写时复制意味着改一个 4K 的块也要落一次盘,加上 btrfs 自己的元数据双写,SSD 上的写入量比 ext4 高得多。装机的老手一般会顺手把快照保留策略设成「只留最近 N 份 + 每天一份留 30 天」,而不是无脑攒着。我给客户配的时候就是留 7 个日备 + 4 个周备,磁盘占用一直稳在源数据的 1.3 倍左右。

什么时候 btrfs 不值得上

也不是所有机器都适合。文件数量极多(几百万小文件)的小目录树,btrfs 的元数据压力会明显变大;只跑一个静态站点、每天手动 scp 一份 tar 出去的小机器,上 btrfs 反而是给自己添麻烦。我的判断标准很简单:数据在变、需要多个时间点能回退、并且磁盘 IO 还扛得住,那就上 btrfs 子卷快照;否则老老实实写脚本备份更省心。

最后再强调一次那件最容易被忽略的事:快照解决的是「怎么快速回到过去」,不是「怎么保证东西不丢」。前者 btrfs 做得很好,几秒钟的事;后者必须靠异机复制。只做前者不做后者,等于把全部身家押在一块盘上。

    相关评论

    阅读本文后您有什么感想? 已有人给出评价!

    • 8 喜欢喜欢
    • 3 顶顶
    • 1 难过难过
    • 5 囧囧
    • 3 围观围观
    • 2 无聊无聊

    发表评论

    昵称:
    表情: 高兴 可 汗 我不要 害羞 好 下下下 送花 屎 亲亲