摘要

  • Mendel Rosenblum 与 John Ousterhout 的 Sprite LFS 把许多随机小写入变成大型顺序传输,但被新版本取代的旧数据仍需由分段清理器回收。
  • 1992 年论文最耐久的贡献是“写入成本”口径:新数据之外,清理器读出并重写活数据的流量也计入账内。
  • 后续 BSD 实现证明这笔交易有明确边界:真实空闲时间足够时,清理可以留在后台;磁盘趋满、随机更新增多、余量消失时,债务会直接争抢业务带宽。

快速确认只覆盖了一层现实

应用收到写入成功,往往便把操作视为结束。存储系统看到的却是另一幅图景:新版本已经落盘,旧版本只是失效,并未从介质上消失;干净分段的库存正在变化;下一次崩溃后,系统还要判断哪些版本才是当前状态。

日志结构文件系统的价值,正是在这几层现实之间建立了可测量的联系。Mendel Rosenblum 与 John K. Ousterhout 在 1992 年发表的设计,不只是把文件系统“写成日志”。Berkeley 的 Sprite 团队真正实现、运行并观察了它。Ousterhout 后来的研究跨越操作系统、分布式系统、存储与编程语言,但 LFS 这一段尤其值得重读,因为它只有把清理器算进去才成立。

前台规则很薄。文件数据和元数据先进入缓冲区,再合成大型顺序传输。大量同步、随机的小写入因此变成异步长写。读取并不从头扫描日志:常规索引仍指向当前数据,inode map 保存每个 inode 的最新位置。日志化改变的是放置方式,而不是取消随机读取能力。

每次修改都写出新版本。旧版本随即失效,却留下分散空洞。日志绕回磁盘前端后,如果逐个填洞,写入又会碎成随机操作。Sprite LFS 因而把磁盘划为较大的分段,只回收完整分段。

清理器才是写路径的下半场

清理器读取候选分段,识别仍然有效的块,把活块紧凑地写到别处,然后释放原分段。segment summary 记录块所属的文件和逻辑位置,清理器据此同当前元数据核对存活性;崩溃恢复也借助这些摘要从检查点向前滚动。

候选分段里活数据的比例决定了账单。一个大多已死的分段,只需搬很少数据便能换回很多空间。一个几乎全活的分段,则要大量读取和重写,最后只释放一点容量。于是,“未使用容量”不再只是闲置资产,而是给清理器留下选择的性能储备。

Rosenblum 与 Ousterhout 用写入成本把这件事说清楚。分母是新写入的有效数据,分子则是接受这些数据所需的全部磁盘流量,包括清理时读出和重写的活块。成本为 1 是理想状态;成本为 10 意味着只有约十分之一的原始带宽真正服务新数据。这个口径拒绝让前台低延迟替整套系统下结论。

选择清理对象还需要判断冷热。简单的贪心策略总挑利用率最低的分段,看似合理,却会在存在局部性时失效:冷数据长期困在半空分段里,热数据则可能刚搬完又被更新。论文提出的成本收益策略同时考虑利用率和最年轻块的年龄,形式近似 (1-u) × age / (1+u)。

年龄只是稳定性的代理。冷分段即使还有较多活块,也值得一次搬好;热分段则等到更空再清。论文所述模拟中,这种分离相对贪心策略最多把写入成本降低一半。但它不是预言。工作负载一旦换挡,昨天的冷数据就可能成为今天反复搬运的来源。

最亮眼的数字有适用边界

原论文的微基准没有包含清理,因此展示的是前台路径的最好情况,而不是稳态表现。更有分量的证据来自四个月的实际运行:在当时的 Sprite 环境中,观测到的写入成本约为 1.2 至 1.6,长期写入性能约为最大顺序带宽的 70%。

这是运行代码给出的真实收据,却不是跨设备、跨容量、跨负载的常数。作者明确承认经验仍然有限。恢复也有独立成本:checkpoint 固定一个可知的 inode-map 状态,之后借助分段摘要向前重放。检查点越频繁,日常开销越高;越稀疏,故障后要检查的尾部越长。快速确认、检查点完成和可控恢复是三张相关但不可互换的收据。

反证把设计边界补完整

Margo Seltzer、Keith Bostic、Marshall Kirk McKusick 与 Carl Staelin 随后在 BSD 上实现 LFS。他们没有复述一个全胜故事。改进聚簇后,传统文件系统在一些场景可以取得相近表现。LFS 的优势主要集中在元数据密集、含大量小文件的负载;大文件表现更接近。

1995 年的一项比较中,在测试磁盘仅使用一半时,清理器开销已让事务处理性能下降超过 33%;论文还讨论了此前高达 40% 的降幅。另一项清理启发式研究却让最繁忙系统 97% 的清理在后台完成。两者并不矛盾。“后台”说明付款发生在何时,不说明债务不存在。只要真正的空闲时间存在,系统可以在业务争用前完成搬运;一旦持续写入、空间趋紧、空闲窗口消失,同一批工作就进入前台。

后续自适应 LFS 研究进一步画出边界:频繁小写、读取多被缓存吸收、清理有足够空闲时间,是有利区间;接近满盘、随机更新、几乎没有空闲,则是不利区间。改变分段大小、清理策略、缓存或读取布局可以扩大适用区,却不能消灭交易本身。

因此,Ousterhout 与 LFS 的意义并非一句“顺序 I/O 更快”。更重要的是,Sprite 团队让延后的工作拥有了名称、指标和运行证据。追加记录说明一个版本已经进入系统;清理余量、恢复状态与容量储备说明系统能否继续兑现承诺。

来源