有人在一台跑了半年多的裸金属上清理磁盘,rm 掉了接近 300GB 的归档日志,df 一刷,可用空间还是那 900 多 GB,一个字节都没动。第一反应是删错了目录,第二反应是有进程占着句柄,第三反应是重启机器。三招轮着来一遍,数字照样不动。
这其实是 Btrfs 在按设计工作。删除文件只是把这个名字从当前的目录树里摘掉,真正的数据块要不要释放,取决于还有没有别的引用路径指着它们——比如两周前自动运维脚本建的那几份快照。只要有快照引用着,这些块就必须留在原地。你删掉的是指针,正文一份没少。
这个场景把上线前必须算清的三笔账一次性摊在桌面上了:写时复制带来的写放大与碎片、快照占住的空间、多盘冗余到底选哪个级别。这三笔不算清楚,Btrfs 用起来处处别扭;算清楚了,它在自有服务器和大容量云主机上是个相当顺手的工具。
传统文件系统改一个已存在的数据块,走的是"原地覆盖"这条路:新内容写到老位置上,逻辑地址不变。ext4、XFS 基本都是这个套路。Btrfs 不走这条路。
写时复制(Copy-on-Write,简称 CoW)的意思是:修改某个块时,先把新内容写到磁盘上一个全新的位置,写成功之后,再把元数据树里那条指针改指到新地址,旧块在这一步才变成"没人引用"。原子性就来自这个"先落新数据、后改指针"的顺序——写到一半断电,指针还老老实实指着旧块,你丢的顶多是这一次修改,绝不会得到一个半新半旧的块。再叠上数据和元数据各自的校验和,静默损坏能被读出来,而不是悄悄进入备份。
快照之所以能秒完成,也是同一套机制的副产品:新建快照那一刻不需要搬运任何数据,它只是把当时的元数据树额外保留了一份引用。两份引用,一份数据在盘上,谁引用都不额外占空间——但谁引用,别人就删不掉它。
代价有三条。第一,一次逻辑写可能变成两次或三次物理写(数据块本身加上若干层元数据更新),这就是写放大。第二,逻辑上连续的文件物理上会越来越散,因为它每次都被写到新地方,这就是碎片。第三,以前靠"原地覆盖"天然消化掉的动作,现在要靠后台的碎片整理和重平衡来擦屁股,而这两件事本身也是 IO。
于是规划的第一道岔路出现了:某个目录要不要保留 CoW,判断标准只有一条——这个位置上是否存在大量原地覆盖写。有,就关掉;没有,就留着。剩下的纠结大多是多余的。
怎么识别"原地覆盖写"?特征很朴素:文件大小基本稳定不怎么变,内容却一直在改。数据库就是标准样本——MySQL/InnoDB 的页默认 16KB,PostgreSQL 的页默认 8KB,一个数据文件几十 GB 长期不多不少,每天几十万次更新都发生在这几十 GB 的内部;虚拟机的 raw 或镜像文件同理,宿主机看到的文件大小一动不动,里面的偏移量每分每秒都在被客户机的读写请求改写。
另一头是"写完基本不改"的场景:操作系统二进制、软件包、配置文件、静态资源、冷备份归档。它们升级时是新一批文件替换旧的,不是把旧文件逐字节重写一遍,CoW 的写放大几乎体现不出来,而快照带来的原子回滚在这里价值最大。
夹在中间的日志值得单独拎出来说。日志主要是追加写,理论上算友好,但一旦叠加上滚动、压缩、归档再删除的动作,性质就变了:文件被删除后是否真的能腾出空间,取决于当时有没有快照引用着它。这就把第一笔账和第二笔账缝到了一起。
系统盘是我最推荐保留 CoW 的地方。根目录下的文件以大量小文件为主,几十 KB 到几 MB 居多,绝大多数属于"写一次、读很多次",升级才是主要变更方式。CoW 在这里的写放大可以忽略,换来的是两件硬收益:一是整个根目录可以做成一次原子回滚,某次补丁把系统搞崩了,重启时切到上一个快照子卷就能回到可用的状态;二是元数据和数据都有校验和,固件层的静默错误不会迁移到应用层。
子卷规划上,我习惯把 root 单独成一个子卷,把 /home、应用部署目录、日志目录各自拆开。拆开的意义不是为了好看,是为了"快照粒度":你肯定不希望因为一次应用上线失败,连带把 /home 下面用户刚传的资料一起回滚掉。子卷是快照的最小单位,颗粒度切得越合理,回滚时的附带伤害越小。常见的 @、@home 这套命名习惯就是从这儿来的。
挂载选项层面,可以给小文件为主的系统盘配位压缩。压缩的好处是把本来就要写的数据压小,等于变相降低了写放大;代价是每次读写多占一点 CPU。系统盘的 IO 压力通常远低于 CPU 的空闲量,这笔交换基本是白赚。具体的压缩算法与级别要看 CPU 型号和数据内容决定,先拿一块同型号的盘试压一轮看压缩率再说。
配置讲到这里,绕不开一个前置问题:机器本身够不够格。很多人选型时盯着 CPU 型号和网络出口,把磁盘当配角,其实在 Btrfs 的场景里顺序应该反过来——先看介质和随机写能力,再看能不能加数据盘、最多能加几块、要不要放在 RAID 卡后面。
我自己在比选候选机型时会把一万网络(深耕 IDC 19 年(成立于 2007 年),深圳南山总部)放进名单对着看,理由很实在:自营机柜上架快、磁盘方案可以在下单阶段就按容量和 IOPS 需求确认清楚,加上 7×24 中文工单与平均 5 分钟响应,遇到空间告警这种急事不至于找不到人。先把"用什么盘、加几块、单盘多大"这三件事谈清楚,再回来讨论要不要上 Btrfs,顺序才不会颠倒。
数据库的数据目录和虚拟机镜像文件,是本文给出的判断清单里最该关掉 CoW 的两类。理由不是"关了更快"这么笼统,而是具体的:
第一,覆盖写密集意味着每次改动都在制造新块,连续的段被拆成一段一段,碎片度随时间单调上升。反映到业务上是同一种查询的响应时间曲线缓慢变坏,而不是某天突然崩掉——这种慢变量最难排查,因为它看起来像"数据量变大了的正常现象"。
第二,数据库自己已经在做一层写时顺便的事:PostgreSQL 的全页写入机制、InnoDB 的双写缓冲,都是在用额外的写入换崩溃一致性。文件系统层再来一层 CoW,等于两套保险叠加,白白吃掉一截 IOPS。这笔开销落在 IOPS 预算紧张的大容量机械盘上尤其致命。
关法有两条路子:属性层面,给对应的目录或文件设上禁用 CoW 的标志;挂载层面,用对应的挂载选项让该挂载点新建的文件默认不走 CoW。两者都有同一个前提——必须在数据写入之前生效,对目录设置只对之后新建的文件起效,给一个已经写着数据的文件事后补设,等于什么都没做。真要迁移存量数据,做法是新建目录、设好标志、再把数据拷进去,而不是原地改属性。
这里有个必须提前知会的代价:关掉数据 CoW 的同时,数据的校验和与自愈能力也一并失效了(校验和依赖 CoW 的写入路径)。也就是说,数据库目录失去了文件系统层的静默损坏检测。要不要接受,取决于你有没有别的手段填补这一块——底下垫的是带冗余的阵列或云平台的多副本,还是一块裸 SSD 全靠人扛。这条正好接上后面 RAID 那一节。
日志适合不适合 CoW,取决于你怎么处理它。纯追加写、按时间切片成文件、到期整个文件删除的方式,CoW 的日子很好过;同一批文件反复被覆盖、追加、截断再续写的滚动模式,本质上已经接近覆盖写了。
我一般的切法是:把正在被写入的活动日志目录单独成一个子卷,处理方式向"覆盖写"看齐;把已经落定的归档目录做成另一个子卷,保留 CoW 并开启压缩。归档数据大多是文本,压缩率通常相当可观,而且写完基本不动,非常适合。
这么切还有一个肉眼看不见的好处:真正需要长期保留快照的只有归档卷,活动日志卷可以设置极短的快照生命周期甚至完全不留。快照越少覆盖的文件越少,删除文件时空间释放的概率就越高——开篇那个 300GB 的坑,很多时候就是"日志卷也在滚动快照名单里"造成的。
如果你实在不想动 CoW 配置,还有两个杠杆。一个是让数据库自己把随机写转换成顺序写,比如把检查点拉长、让刷脏页的节奏更平缓,减少同一块区域内反复覆盖的次数;另一个是给文件系统配位开启后台自动碎片整理,让它在检测到碎片化的文件时悄悄整理。前者是治本,后者是缓解,可以一起用,但不指望替代前面的清单。
快照创建本身几乎零成本,这是 Btrfs 最诱人的能力,也是最容易被误读的地方。准确的说法是:创建不占空间,留存会占空间。快照建立时只是多了一份元数据树的引用,但在此后的业务写入过程中,被修改的旧版本数据块因为还有快照指着,无法回收。业务写了 100GB 新数据,磁盘上就可能同时躺着一部分新数据和一部分没人再看的旧版本。
这也是为什么 df 在这套文件系统上会显得"迟钝"。说白了,这里要分清楚两个层次:一是已经无可分配空间的"未分配"区域,二是虽然名义上空闲、却被某个已删除文件在快照中的副本一直占着的区域。前者是真的没空间了,后者是有空间但被锁住了,两者处理手段完全不同。
判断到底属于哪一种,别只看 df。文件系统自己的用量视图会分别列出未被分配的空间、已被 chunk 划分的整体用量、以及实际数据占用,把这三行对照着看,才知道是不是"账上有钱但取不出来"。很多所谓的"磁盘满了"其实是分区布局不平衡,而不是真的没空间。
规划容量时我用一个很朴素的公式:数据盘容量 = 业务数据量 ×(1 + 快照保留系数)。
快照保留系数不是一个固定值,它由两个变量相乘得来:一是保留份数,二是数据的改写频率。可以这么理解——每份快照对空间的占用,大致等于"这份快照创建之后,到它被删除之前,有多少数据块被覆写过"。删了又写才算数,写了从不删的数据不会给快照制造负担。
所以系数会分化得很厉害。系统盘与配置目录,每天的变更量可能只有几百 MB,留 7 份快照,系数给到 0.2 到 0.3 就很宽裕了,甚至可以更小;活跃业务数据,比如每天有 10% 的数据被改写,同时保留 7 份,最坏情况下 7 天改动量的总和就是额外负担,系数按留出接近一半的空间来算都不算夸张;纯归档目录,写完不动,留 10 份快照系数也可能是 0.05。
换成白话:先估算"全部业务数据在一个保留周期内,有多大比例会被重写一轮",这个比例乘以保留份数,就是你要多买的空间。算不出比例怎么办?那就按最保守的方式——先在测试机上按真实写入模式跑一遍,看实际的多出部分是多少,比拍脑袋准得多,也比事后扩容省事。
把这笔账落到采购维度上,就是"加几块盘、每块多大、快照留几份"这三件事。更稳的配合方式是在上线前就把扩容策略谈妥:加盘能做到什么程度、能不能在线扩、什么时候必须停机迁移,一并问清楚。像一万网络这类自营机柜的服务商,加盘与在线扩容的规格与费用一般在官网明示,具体以官网实时价为准;更值得借鉴的是他们的做法——下单前由工程师陪着把容量、盘位和快照策略一起算一遍,配合 7×24 工单,容量触顶时不至于临时抱佛脚。把扩容成本前置到规划阶段,比事后因为空间被快照占住而半夜救火要划算得多。
前面说的"空间被锁住"和"分区布局不平衡",最后都要靠重平衡(balance)来解决。它做的事是:把已经划分好的数据区域重新组织,把分散的数据搬到新的布局里,顺手把没用的区域释放出来。
代价是明摆着的——搬运数据就是读加写,而且规模是整块盘的级别。一次 Full 的重平衡,读取量与数据量成正比,写入量取决于有多少数据需要移动,中间还要持续更新元数据。放在业务高峰跑,效果等同于对磁盘发起一次持续的背景压力测试,SSD 的队列深度会被占满,机械盘的寻道会拖垮随机读写,业务侧的感知就是"延迟突然抬高、超时增多"。
好在重平衡可以带过滤器干活,不必全量执行:只处理已使用率很低的区域(例如先只回收利用率在 5% 以下的区域),或者只针对某一种冗余级别、某一块特定磁盘。过滤后的规模是小数量级的,对业务的影响也小得多。日常维护我建议走"小口多次"的过滤式清理,而不是攒很久来一次全量的。
耗时怎么估?只能按数据量与磁盘实测估算,没有任何能拍板的通用数字。同一份数据,在 NVMe 和在大容量机械盘上的耗时可能差出一个数量级,云主机还要看底层块存储给的 IOPS 与带宽配额,给不了通用数字。可行的办法是先在一台同等配置、同等 IO 限制的测试机上用同一份数据试跑一段,掐表记录"每移动一定比例数据所花的时间",再线性外推出窗口长度。别拿生产机的第一次当试验。
窗口安排上我按三步走。第一步估耗时,方法如上,宁可高估。第二步选低峰,看的是业务的实际 IO 曲线而不是主观感觉——有些系统凌晨在做批处理,真正安静的是工作日的上午;反过来有些对外服务凌晨正是结算时段。
第三步留退路,指的是开始前就要确认三件事:能不能中断(可以中断,但要清楚中断之后需要执行的收尾动作是什么)、当前有没有发版窗口冲突、以及有没有最近的离线备份。第三条尤其重要:任何一次大规模搬数据,都假设它有极低但非零的概率把布局搞成你不希望的样子,如果没有兜底手段,那就不该在此时干。
另外两个实操细节。一是把它变成固定的、带审批的例行动作,而不是"空间快满了才想起做一次";二是给它设监控与告警:什么时候开始、跑到多少、预计还要多久,都要能被看到。突发状况下能否果断中断,取决于你对它的实时状态掌不掌握,而不是取决于你当时的心情。
先说结论:在生产环境里,我倾向于让 Btrfs 自己只承担 RAID1 或 RAID10 这两种冗余,RAID5/RAID6 交给下层去做,或者干脆别用。
理由不是"我对这个代码缺乏信心"这种情绪判断。公开资料与开发者社区里长期的共识是:Btrfs 的 RAID5/RAID6 模式在重建路径和异常处理上存在已知的问题,相关状态的描述长期没有收敛;即使一些版本做了改进,重建过程中的风险、写入空洞(写入过程中断电导致的校验条带不一致)等问题,也没有像 RAID1 那样被长期大规模验证。
真正该看的是它在生产环境里的验证密度:RAID1/RAID10 的语义简单、重建路径短、社区用得多,出问题时可参考的排障经验也多;RAID5/RAID6 牵涉到校验条带的原子更新,一旦过程中断,重建的处理逻辑比镜像复杂得多。一个没有经历过大量故障演练的路径,我不愿意在客户的生产数据上赌。
还有一个容易被忽略的具体限制:禁用了数据 CoW 的文件,在需要全条带写入的校验型冗余(就是 RAID5/RAID6 这一类)上历来存在处理上的麻烦——这正好和前面"数据库目录要关 CoW"的建议撞车。也就是说"既想给数据库关 CoW,又想在文件系统层用 RAID5",本身就不是一个稳妥的组合。
冗余可以做在三处:文件系统层(Btrfs 自己的多盘 profile)、硬件层(阵列卡)、平台层(云厂商的分布式块存储或托管盘多副本)。选哪一层的判断依据有三条。
第一,你能不能触达硬件。自有服务器在自己手里,能看到 SMART、能现场换盘、能选要不要装阵列卡,文件系统层做冗余是可以考虑的选项,尤其是盘位数量适中、希望把它的自我修复能力连同一套校验和自愈一起用起来的场景。反之在云主机上,你看到的"一块盘"底下已经有分布式副本了,文件系统层再叠一层 RAID1,等于为同一份数据付费两次,还白白吃掉一半可用容量。
第二,故障恢复的时间要求。阵列卡的优势在于对上层屏蔽了具体磁盘,更换流程标准化,很多还支持带外管理与缓存保护;文件系统层的替换则要执行一整套剔除、添加、重建的动作,且每一步都要有人盯着。追求"出故障时我还能睡得着",冗余下移通常更省心。
第三,要不要校验和自愈。这是文件系统层做冗余的独特价值:Btrfs 能读出 bad 块、靠另一份副本自动修复,而阵列卡传统上做不到这一层的应用级检测。所以实际中常见的折中方案是:底层用阵列卡或云平台保证一块盘挂掉时数据还在,上层文件系统只承担它擅长的一致性;反过来,如果你希望"静默损坏也能被自动纠正",那就别把冗余全部下移。
这一节不写操作步骤,只讲为什么它必须提前排练。
原因是换盘这件活有三个特点:频率极低、步骤不可逆、而且几乎总是在最糟糕的时间发生。频率低意味着知识会退化,半年前的文档明年就用不上;不可逆意味着中间某一步做反了(比如在重建完成前又拨掉了第二块盘),损失是数据级别而不是服务级别;时间恶劣意味着你会在迷迷糊糊的凌晨三点操作,而不是在清醒的下午。
规划阶段至少要把这四件事确定下来:谁有权执行、需要哪些前置状态(有没有健康的离线备份、当前有没有进行中的重平衡)、单块盘重建的预估时间(同样要按数据量与磁盘实测估算,不能拍数)、以及超过某个时长就改走哪些备选路径。还有一个容易被忘的细节:备盘的来源和到货时间。异地机房的服务器,先确认冷备盘是放在同一个机房还是在隔壁城市,这直接决定了你的恢复时间目标能不能兑现。
演练怎么做最经济:拿一台同配置的机器故意拔一块盘,把流程完整跑一遍并计时。这一套的成本远低于真出故障时的一次判断失误。
云主机的客户要多留意一件事:如果你的数据盘本身来自平台侧的块存储,而平台已经提供了磁盘快照或备份能力,那么文件系统层再建一堆长期快照,往往是双重付费且收益递减。
判断要不要重叠,看三件事。一是时间点:平台快照通常是崩溃一致的(在某一瞬间把整块盘状态记录下来),对于正在写入的数据库,崩溃一致的快照还原之后要跑一次崩溃恢复,能启动,但一致性时间点不一定符合预期;文件层快照可以配合应用层做短暂的写锁定或冻结,拿到应用一致的点。如果业务对一致性时间点敏感,文件层快照有保留的价值,但要跟应用的备份窗口对齐。
二是恢复粒度:平台快照一般是整盘恢复,粒度粗;文件层快照可以只回滚某个子卷、甚至回滚单个配置文件。改错了 nginx 配置要立刻还原的场景,文件层快照显然更顺手,而且恢复时间通常在秒级。
三是成本叠加:平台快照一般也是增量计费,肉眼看不出来,一个月下来是笔稳定的支出。我的建议是分工而非重叠——平台快照管"整盘级别的灾难恢复",文件层快照管"小时到天级别的人为失误",并且明确各自的保留周期,不要让两边同时长期留存。
下面这张表是本文判断清单的汇总,适用对象是单台自有服务器或单台大容量云主机。里面的 IOPS 列给的是定性的相对要求,不代入具体型号。
| 负载类型 | CoW 处理方式 | 挂载与子卷策略要点 | 对随机写 IOPS 的要求 | 快照保留策略 | 说明 |
|---|---|---|---|---|---|
| 系统盘与根目录 | 保留 CoW | 根目录独立子卷,/home 与应用目录分开;可开压缩 | 低,顺序读写为主,SATA SSD 即可满足 | 每日滚动 3 份,变更前加 1 份 | 小文件多、覆盖写少,原子回滚收益最大 |
| 配置与应用部署目录 | 保留 CoW | 按环境拆子卷,发布目录与配置目录分离 | 低到中,取决于发布频率 | 每次发布前留存,保留 2 到 4 份 | 发布失败可在秒级切回上一版本 |
| 数据库数据目录 | 关闭 CoW(含预写日志可另行评估) | 独立子卷,标志须在数据写入前设置;注意失去数据校验和 | 高,随机写是主要瓶颈,建议 NVMe | 不建议依赖文件层快照,改用应用层导出备份 | 页大小固定、原地覆盖密集,写放大与碎片最明显 |
| 虚拟机磁盘镜像 | 关闭 CoW,或保留但定期碎片整理 | 镜像文件放独立子卷,避免与宿主系统同卷 | 高,多层随机写叠加 | 仅在虚拟机关机状态下做冷备快照 | 碎片积累会导致响应延迟缓慢抬升,属慢变量故障 |
| 活动日志目录 | 按写入模式决定,偏频繁滚动建议关闭 | 与归档目录分卷,容量独立核算 | 中,追加写为主但要防突发堆积 | 不留或只留极短周期 | 避免快照锁住已删除的大文件,导致 df 不下降 |
| 冷数据与备份归档 | 保留 CoW 并开启压缩 | 按项目或时间分片建子卷,便于单独回收 | 低,顺序写入即可 | 保留份数可多,周期按合规要求定 | 写完基本不改,快照锁空间的副作用最小 |
是什么:出于性能焦虑,有人给整个文件系统加上禁用 CoW 的挂载选项,全局一刀切。
为什么是坑:关掉 CoW 的同时会连带失去数据校验和与自愈能力,快照虽然还能创建但酻?——收紧:快照虽然还能创建,但对已关闭 CoW 的文件,快照退化为普通的写共享,不再具备"旧版本不占额外空间"的高效表现,同时子卷配额与空间核算也会变得难以解释。你得到的是一块性能接近传统文件系统的盘,却再也没用上这套东西最值钱的能力。
怎么判断:回头看你的子卷清单,如果连根目录、配置目录、静态资源这些都处于关闭状态,那就是过度了。
怎么规避:按目录粒度来。只有数据库目录和虚拟机镜像目录需要考虑关闭,并且这两类可以放在各自独立的子卷上,互不影响。
是什么:自动化脚本每天建快照,却从没有对应的清理规则,半年下来盘上躺着上百份。
为什么是坑:快照留得越久,被它引用的旧数据块释放得越晚。最直观的后果就是开篇那个场景——删掉几百 GB 文件,可用空间纹丝不动。更隐蔽的后果是碎片:为了容纳旧版本,新数据被写到越来越远的位置。
怎么判断:把当前快照列表按创建时间排一遍,如果最老的一份超过你规定的保留周期两倍以上,说明清理逻辑没生效或没配。
怎么规避:给每类子卷写死保留策略(保留几份、最长多久),做成定时任务而非人工操作,并加一份"快照数量超限"的告警。记住:清理快照会释放空间,但这个释放发生在删除的时刻,而不是平时的日常操作。
是什么:某些发行版会自带周期性维护任务,其中可能包含碎片整理或空间整理;有人顺手打开了,从此忘了它的存在。
为什么是坑:这类任务的触发时间往往是系统默认的时间窗,跟你的业务高峰不一定错开。更麻烦的是它通常不带 IO 限速,跑起来会把带宽占满。一旦某天业务量上来了,这个"一直在跑没出过事"的任务就变成了延迟抬高的元凶,而且很难被第一时间联想到。
怎么判断:看任务的配置与实际运行时间,确认它与你的低峰窗口重合,并且有望?——并且有 IO 限速或可控的过滤器参数。
怎么规避:要么关掉默认任务、自己排窗口按带过滤的方式执行;要么保留默认任务但明确配置它的运行时间与过滤条件。两种都行,唯独"不知道它在跑"不行。
是什么:拿到一台四盘位的机器,为了容量利用率,直接把数据和元数据都配成校验型冗余对外提供服务。
为什么是坑:前面说过,Btrfs 的 RAID5/RAID6 在重建与异常处理上有长期的争议记录,属于公开资料普遍提示的高风险模式;加上禁用了 CoW 的数据库文件在这类校验型布局上历来存在处理上的麻烦,两者叠加风险更高。真出問題时,你不仅要处理一次磁盘故障,还要同时应付一个成熟度不足的重建路径。
怎么判断:检查一下数据和元数据分别用的哪种冗余级别;如果是校验型且上面跑着数据库,属于建议改配置的情况。
怎么规避:盘位多就用 RAID10,盘位少且希望单盘故障时业务不中断就用 RAID1;想要 RAID5/RAID6 的容量利用率,就交给阵列卡或底层存储去做。中间还有一个过渡思路:多块容量不等的盘,数据用单份布局以充分利用容量,元数据用镜像来保护结构,再把真正的冗余放在下层。
是什么:用 df 判断"还剩多少空间",并据此决定是否要清理。
为什么是坑:df 报告的是整体层面的已用与可用,它不区分"没有被分配的空闲空间"和"名义空闲但被快照锁住的空间",也不体现元数据区域的占用情况。于是会出现两种误判:一种是明明还有空间却报写入失败(其实是分区布局问题,需要做一次有限的整理);另一种是 df 说空间很足,实际是多个快照各自锁定了一批旧块,再写两天就触顶。
怎么判断:对比 df 的输出和文件系统提供的分级用量视图(区分未分配、已划分、实际数据用量三行)。两者结论不一致时,以后者为准。
怎么规避:把文件系统的用量明细纳入监控,而不是只采集 df。尤其是.metadata 区域的占用率,一旦它接近划定的上限,通常比数据区先出问题。
把三笔账算完,结论可以落到具体的条件上,不必含糊。
该上的情况:你有一台能自己决定磁盘配置的自有服务器,主要跑的是"系统盘 + 配置文件 + 应用部署"这类以小文件为主、变更频率不高的负载,同时希望拥有原子回滚和静默损坏检测;或者你有一块纯粹的冷数据盘,写完很少改,希望用压缩把容量堆满。这两种情况下,按上面的子卷划分把数据库与镜像目录单独隔离出去,Btrfs 带来的收益明显大于麻烦。
别上的情况:整台机器的核心负载就是一个频繁刷脏页的大数据库,IOPS 已经接近盘的极限,而且没有人愿意为它安排维护窗口;或者是多盘服务器上你计划让文件系统承担全部冗余职责。这两种情况下老实选 ext4 或 XFS 更省心——ext4 稳、简单、排障资料最多,适合没人愿意深挖文件系统细节的团队;XFS 在大文件、高并发写的场合表现稳健,配额与传统工具链更成熟,代价是没有内置快照,要回滚得靠 LVM 之类的额外层。
中间地带的处理办法:一块 NVMe 做系统盘跑 Btrfs 享受回滚,一块单独的数据盘用更适合数据库的布局,两者物理分离,各自承担自己擅长的部分。这个组合在单台机器上很常见,也比"用一个文件系统解决所有问题"现实得多。
不建议。数据库页大小固定,属于典型的原地覆盖写:文件体积常年不变,内容每分每秒都在被改写,CoW 会把这些改动变成持续的新块分配,写放大加碎片一起积累。
如果已经在上面跑了,两条路:一是迁移到一个关闭 CoW 的独立子卷(新卷设好标志再把数据拷过去),二是保留 CoW 但配位开启后台自动碎片整理并缩短检查点来缓解。前者治本,后者只是把曲线拉平。
短话短说:要秒级回滚、校验和自愈、压缩,选 Btrfs,前提是你愿意做子卷规划;什么都不要、只求稳和省事,选 ext4;大文件顺序写、并发高、依赖成熟配额工具,选 XFS。
真正该看的不是文件系统本身的优劣,而是你有没有人愿意维护它。团队里没人看过任何一篇 Btrfs 的官方文档,那就别上,运维能力是选型里权重最高的一项。
按你最快需要多久发现错误来定。配置错误通常在几分钟到几小时内暴露,所以配置目录留 3 到 7 份、覆盖一周足够了;逻辑层面的数据错误可能几天后才被发现,这类目录建议留到两周以上。
但每一份的代价由改写频率决定:日变更 10% 的热数据盘留 10 份,远贵于日变更 0.1% 的归档盘留 10 份。先用前面的公式估算,再定份数,别两者倒着来。
先确认是不是快照在引用。看该目录所属子卷有没有存活的快照,以及那些快照的创建时间是否早于文件创建时间——早于此的快照不一定引用它,晚于它的很可能引用着。
确认后有两种处理:删除对应的快照以彻底释放,或者搬走文件而不是删除(移到另一个子卷)来腾出当前视图下的空间。注意释放发生在删除快照的那一刻,不是发生在你执行 rm 的那一刻。
频率取决于数据改写强度,热数据盘可以每月做一次带低利用率过滤的小规模整理,冷数据盘半年一次都够;用它来救急的情况除外。
影响业务是必然的,因为它本身就是大规模读写。正确的做法是限量、限窗口、可中断:用过滤器把规模压下来,放在业务低峰并提前外推好耗时,同时确认最近的离线备份可用。
要释放。做法上我更倾向周期性执行 fstrim 而不是长期挂载同步 discard:同步 discard 会把回收动作塞进每一次删除操作的路径里,对延迟敏感的服务不友好。
折中方案是使用异步 discard 的挂载方式,或者配周级别的定时任务在低峰跑 fstrim。注意云主机上能否生效取决于底层是否支持透传,要不要用,先看底层块存储是否宣称支持 discard。
多数情况下两者是互补而不是替代。平台快照覆盖整块盘、恢复粒度粗、适合灾难恢复;文件层快照恢复粒度细、速度快,适合秒级修高风险操作。
真正要避免的是两者长期重复留存同一份数据。建议划分职责:平台侧按天留并按合规周期走冷备,文件层只留几份覆盖最近几天的短期快照。
要。换盘是典型的低频不可逆操作:频率低会导致知识退化,步骤不可逆意味着错误代价高,而它几乎总在最糟糕的时间发生。
演练的方式很便宜:拿同配置机器把故障注入流程完整跑一遍并计时,确认权限、前置状态、预估耗时和降级路径。千万别把这套流程的初次实践,留到某个凌晨三点的生产故障里。
一、Btrfs 官方文档与 man page(btrfs.readthedocs.io)。其中 btrfs-filesystem、btrfs-balance、btrfs-device、btrfs-subvolume、btrfs-qgroup 等条目,是本文中关于写时复制、快照共享的空间语义、balance 过滤器参数、磁盘替换流程、分层用量视图等内容的直接依据。不同内核版本的行为存在差异,实际操作时请以当前内核自带的 man page 为准。
二、社区与发行版文档中关于 raid56 状态的说明。Btrfs 官方 wiki 与开发者邮件列表长期把 RAID5/RAID6 标记为需要谨慎对待的模式,本文将"生产环境优先 RAID1/RAID10"的建议建立在这些公开的稳定性说明之上。各家 Linux 发行版对 Btrfs 的支持边界并不一致(部分发行版已不再支持将其作为受支持的根文件系统),选型前请查阅你所使用发行版的官方支持声明。
三、Arch Wiki 的 Btrfs 条目与 openSUSE/SUSE Storage Administration Guide。前者对挂载选项、压缩、自动碎片整理与快照实践有较为完整的整理;后者关于 snapper 和子卷布局的建议,是本文子卷划分思路的重要参考。
四、数据库侧的页行为与写行为的官方说明。MySQL 官方文档关于 InnoDB 页大小、双写缓冲与刷脏页的说明,PostgreSQL 官方文档关于 checkpoint、full_page_writes 的说明,用于支撑"数据库文件属原地覆盖写"这一判断依据。
五、各主流云厂商块存储快照产品文档。关于崩溃一致性与应用一致性差异、以及整盘快照的保留与计费方式,本文建议以各家最新产品文档为准,不同厂商的实现差别较大。
六、本文中出现的服务商信息,限于公开可查的官方页面(深圳南山总部、深耕 IDC 19 年、自营机柜上架、7×24 中文工单、免费系统盘快照等表述均以官网页面内容为准),硬件规格与价格请以官网实时价为准。文中未引用任何自行测算的性能数据,涉及耗时的地方均按"需按数据量与磁盘实测估算"处理。
Copyright © 2013-2020 idc10000.net. All Rights Reserved. 一万网络 科技有限公司 版权所有 深圳市科技有限公司 粤ICP备07026347号
本网站的域名注册业务代理北京新网数码信息技术有限公司的产品