第8章 文件系统:文件慢,不一定是磁盘慢

文件系统问题要先分层,区分缓存、页缓存、文件系统路径和底层设备,不能直接等同于磁盘慢。

本页目录

文件慢,先别急着说磁盘慢

第 8 章先把“文件系统”和“磁盘设备”拆开。

一次文件读写,可能卡在很多地方:

  • 路径名和目录项查找
  • 元数据处理
  • 页缓存命中和回写
  • 文件系统内部锁和写放大
  • 往下游块层发请求之前的等待

所以“文件慢”只说明问题在文件路径上,不足以直接说明问题已经落到设备层。

先把文件 I/O 路径分开

最少要把下面这些位置分开看:

  • 应用发起读写
  • VFS 和路径查找
  • 页缓存命中或失配
  • 文件系统内部处理
  • 写回和脏页刷新
  • 往下游块层发请求

这张路径图不立住,后面看到的延迟就很容易混成一团。

别把写回拖尾、元数据抖动和设备根因混在一起

最常见的错法有四种:

  • 一看到 I/O 慢,就直接说磁盘慢
  • 一看到写延迟大,就直接认定落盘慢
  • 一看到 %iowait,就直接说文件系统是根因
  • 把页缓存、写回、元数据和设备服务时间混成一个问题

这些错法都在跳层。

什么时候先怀疑缓存、元数据和写回

下面这些情况,更像文件系统层在制造症状:

  • 读写时好时坏,工作负载一变形就抖
  • 目录、创建、删除、rename 这类操作异常慢
  • 数据写入看起来已经完成,但后台回写开始拖尾
  • 上层延迟变差,下游设备却没出现同样程度的异常

这时候先别急着冲到磁盘章,先把文件系统内部路径补全。

一个最典型的错法:把写回拖尾当成设备根因

现场里经常会看到一种情况:应用写延迟突然变差,大家第一反应都是“底层盘不行了”。

但很多时候,前面先变坏的并不是设备服务时间,而是:

  • 脏页积压
  • 后台回写节奏不稳
  • 文件系统内部锁或元数据路径变重

如果这一步不分开,后面就会把文件系统层的问题误读成块设备问题。

还要再补一层更硬的现实: 应用看到的逻辑 I/O 和底层真的发生的物理 I/O,常常不是一回事。记录对齐、读改写、日志保护和元数据更新,都会把很小的一次逻辑写放大成更大的物理读写。现场里最常见的争执,就是应用说“我没写这么多”,存储说“盘上就是这么忙”,中间丢的正是文件系统这层放大。

先把文件路径、元数据和写回拆开

先把文件 I/O 路径画完整

图里至少要有:

  • 应用读写
  • 路径查找和元数据
  • 页缓存
  • 文件系统实现
  • 写回
  • 块层

以后排查文件慢时,先把症状标回这张图。

先把“文件慢”和“设备慢”拆成两组证据

如果更像文件系统层问题,优先找:

  • 缓存命中和失配变化
  • 元数据操作异常
  • 脏页和写回行为
  • 文件系统内部等待

再补一个容易被忽略的读方向陷阱: 预取污染。文件系统如果把随机读误判成顺序读,会主动发起应用根本没要的预取 I/O,不只会平白打爆读带宽,还会把原本有用的页缓存冲掉。

如果更像设备层问题,再去看下一章的块层和服务时间。

上层慢、下层不明显时,先别越级

应用层和文件系统层都慢,但块层和设备层还没有同样强的证据时,先停在这一层继续拆。别急着越级宣布硬件根因。

文件路径拆开以后,再看块设备是不是真的慢

第 8 章解决的是“文件路径上哪里可能先变慢”。第 9 章接着解决“块设备、队列和服务时间到底怎么分开看”。