空间回收没卡住,它只是在等明天早上 09:29

· 4 分钟 · devops synologybtrfssnapshotsstoragenas

我问错了问题

我清掉几个文件夹,在 NAS 上点了空间回收,然后等。几个小时后,存储管理员那张卡还写着 running,可用空间看起来跟早上一样。我的问题是「它为什么什么都没回收」。

它回收过了——两次,而且其中一次比我删掉的东西大得多。测量回答的是另一个问题,而这才是这件事里最有意思的地方。

在相信任何东西之前,先给可用空间上定时采样

我没有去看那张进度卡,而是给 volume1 的可用空间做了当天每五分钟一次的采样:

时间可用事件
08:59 → 09:241134.1 GiB平——什么都没在回收
09:29+69.0 GiBClass 快照 …10.14-09.29.02 轮转
09:34+46.8 GiBVideo 快照 …10.14-09.30.35 轮转
15:28:45—DSM 日志:Start to empty all recycle bins.
15:34+5.0 GiB清回收站结束——里面只有 5 GiB
16:35 → 17:39−39 GiB新数据写入(一阵爆发)
15:00 → 20:44−47.2 GiB净值:这个卷那天下午丢了空间

两次回收,合计约 121 GiB;然后 47 GiB 的新写入把下午吃掉了。「什么都没回来」是我这边的读法错误:我拿早上和晚上比,而晚上里面多了一整天的写入。

我特意手动清空的回收站是 5 GiB;我压根没想到的快照是 115.8 GiB。这个比例就是全部故事。

为什么那张卡写着 running,却什么都不代表

$ synostgreclaim --get-all-status --verbose
{"state":"running","num_subvolume_remain":1,"now_runnable":true}
   schedule_table: 168 × 1
   run_time_option: run_all_time

state: running 加上 168 个 1 的调度表和 run_all_time,意思是这个任务被配置成按设计 24×7 都处于 running。它是调度状态,不是进度指示器——所以在某天完全无事可排的日子,这张卡照样这么写。而当时那台机器上没有 synostgreclaim 进程、没有 btrfs balance、md2/dm-3 的 I/O 基本为零。那一刻没有任何东西在被回收,也没有任何东西卡住。

然后是日志,而 DSM 上它们大多是红鲱鱼:

一个永远为真的 UI 状态字段,加上三个永远不会给出答案的日志文件:唯一剩下的仪器,就是随时间变化的可用空间。

没人告诉你的那个机制

空间回收释放的是已删除的 btrfs 子卷。它释放不了仍然被快照钉住的数据。那两个共享文件夹的保留策略是 retention 1(各留一代),所以我删掉的任何东西,都要等到第二天的轮转、大约 09:29 / 09:30 才会变成可用空间,一次跳几十 GB,然后安静 24 小时。

那两次跳变正是这个。它也就意味着,对于「我删了 50 GB 却什么都没发生」这个问题,在这台机器上的诚实答案是:「等明天早上再看」——而如果删掉的数据本来就在某个快照里面,答案是「等那个快照过期,之前不会释放」。

如果重来一次

  1. 采样那个数字,不要采样状态。 每五分钟量一次可用空间,比任何任务卡都更能回答「现在有没有事情在发生」,而且它同时让「回长」变得可见。
  2. 读调度字段,不读状态字段。 run_all_time 解释了那个永久 running,而且不需要任何 bug 存在。
  3. 搞清楚每个共享文件夹的保留策略。 它是决定「删除何时变成可用空间」的那口钟;不知道它,每一次删除都会看起来坏掉一整天。
  4. 把两本账分开。 回收站(5 GiB)和快照(115.8 GiB)行为完全不同,也是两套心理模型。
  5. 重新检查分母。 这个卷平时就在以约 1.5 GiB/时 的速度被正常写入吃掉;回收回来 121 GiB、当天又花掉 47 GiB,只要你只比同一个数字的两个快照,这两件事看起来完全一样。

测量真正告诉我的,是这台机器的趋势

我本来是去修一个卡住的任务,结果带回来的是一条存储趋势:

volume1   42 TB   已用 98%   剩 1.2 TB   近来约 -1.5 GiB/时(8 天 -344 GiB)
volume2   16 TB   已用 100%  剩 70 GB    约 -19 GiB / 2 天
健康      两个卷 btrfs corruption_errs 均为 0
          所有 md 阵列 [UUUU] / [UU],没有在跑 balance
          read/write_io_errs 与九月基线一致

所以有用的结论不是「回收是好的」。而是:相对于写入速率,回收只是一个舍入误差;在保留策略为 1 的前提下,删除并不是我以为的那根杠杆;而该拿来做告警的是趋势,不是那张任务卡。这跟《你的磁盘快满告警在撒谎》是同一课,只是从另一个方向来的:对后果告警(随时间变化的可用字节),因为机制自己的状态不是证据。

Lee Teong Hoe

Lee Teong Hoe · Mr Hoelee

Full-stack developer & DevOps engineer based in Malaysia. I run my own production infrastructure and build web systems for small businesses — this blog is the living record.

Hiring? Profile & stack · Malaysian SME? Website design & development ↗ · All posts