Linux 性能调优系列(二十一): 磁盘为什么慢?从文件系统到 I/O 调优,一次讲透
1 | 作者:李晓辉 |
上一篇我们聊了 Linux I/O 调度器,搞清楚了 none、mq-deadline、kyber 和 bfq 分别适合什么场景。
但是,磁盘性能优化不能只盯着调度器。
比如,同样一块 SSD,同样一个 Linux 系统,为什么有的业务随机读写很快,有的业务却在创建大量小文件时卡得厉害?为什么删除了几十 GB 的文件,虚拟磁盘在宿主机上的占用却没有明显下降?为什么明明是 SSD,业务的 I/O 延迟还是很高?
这些问题,有些出在存储设备,有些出在 I/O 调度器,还有一些就出在文件系统本身。
今天我们就从文件系统入手,聊聊 Linux 服务器上的 XFS 和 ext4,看看格式化参数、挂载选项、SSD 的 discard 机制到底有什么用,最后再用 fio 做一组可复现的性能测试。
文件系统到底在忙什么?
先想一个问题:我们在 Linux 中执行下面这条命令,究竟发生了什么?
1 | echo "hello linux" > /data/test.txt |
对于我们来说,这只是创建了一个文件,往里面写入一行文本。
但对操作系统来说,事情远没有这么简单。
文件系统至少需要处理以下几件事:
- 目录管理:找到
/data目录,建立test.txt这个目录项。 - 索引节点管理:记录文件的权限、所有者、时间戳、数据块位置等元数据。
- 空间分配:找到磁盘上可以存放文件内容的空间。
- 数据写入:将文件内容交给内核和底层块设备。
- 元数据持久化:按照文件系统的规则,记录必要的元数据变更,并通过日志等机制维护一致性。
这些工作并不是简单地把文件名转换成磁盘上的一个位置。
例如,目录项通常负责将文件名关联到索引节点,索引节点再描述文件的元数据及其数据块映射。文件系统还要管理空闲空间、目录结构、权限和崩溃恢复。
可以把文件系统理解成一个仓库管理员:应用程序只需要说出文件名,文件系统就要负责找到文件、分配存储空间,并确保相关元数据按照规定的方式更新。
文件系统位于存储链路的哪一层?
我们把 Linux 存储 I/O 的链路画出来:
flowchart LR
A["应用程序<br/>read / write / fsync"] --> B["VFS 虚拟文件系统层"]
B --> C["具体文件系统<br/>XFS / ext4"]
C --> D["页缓存与文件系统元数据"]
D --> E["块设备层<br/>blk-mq / I/O 调度器"]
E --> F["设备驱动"]
F --> G["SSD / HDD / 虚拟磁盘"]VFS 是 Virtual File System,即虚拟文件系统层。它为应用程序提供统一的文件访问接口,让应用程序不必关心底层使用的是 XFS、ext4 还是其他文件系统。
文件系统负责组织文件和目录、分配空间、管理元数据;块设备层则负责把相关 I/O 请求继续传递给底层设备。
这里要注意,图中的页缓存并不是所有 I/O 都必须经过的路径。例如,应用程序使用 O_DIRECT 时,可以绕过普通的页缓存数据路径,但这不意味着所有文件系统处理和元数据操作都会被绕过。
因此,文件系统调优与 I/O 调度器调优解决的是不同层面的问题。
如果瓶颈出在文件系统元数据操作上,单纯切换 I/O 调度器不一定有效;如果瓶颈出在底层存储延迟上,修改文件系统挂载选项也未必能解决问题。
不同业务,为什么会有不同的文件系统性能?
想象一下下面三种业务。
场景一:备份服务器
每天写入几个几十 GB 的备份文件,主要关心持续写入吞吐量和文件系统容量。
场景二:容器镜像仓库
大量小文件、目录项、元数据操作,还有频繁的文件创建与删除。此时元数据处理能力可能比顺序读写带宽更重要。
场景三:数据库服务器
大量随机读写、频繁的同步写入,以及对延迟比较敏感的 fsync 操作。平均吞吐量不错,并不意味着业务就一定流畅。
所以,文件系统调优的第一条原则是:
先弄清楚业务在做什么,再决定要调什么。不要看到 SSD 就直接套用一组所谓的最佳参数。
XFS 和 ext4 到底怎么选?
在 RHEL 系列系统中,XFS 是默认的本地文件系统。Red Hat 建议在没有明确兼容性、业务或性能理由的情况下,优先使用 XFS。ext4 仍然是成熟、可靠的选择,并不是过时的文件系统。
XFS:适合大型存储和高并发场景
XFS 从设计上就重视大容量文件系统、高并发操作和可扩展性。
它的几个重要特点如下。
第一,元数据操作具备良好的并行扩展能力。
XFS 使用 allocation group(分配组,简称 AG)等机制组织文件系统空间。多个分配组能够帮助不同的操作并行进行,减少部分共享资源上的竞争。
这对于多 CPU、多线程以及大型文件系统比较有价值。
但要注意,XFS 并不是完全没有锁竞争,也不是任何多线程负载下都必然快于 ext4。
第二,支持在线扩容。
当 XFS 所在的底层块设备变大后,可以在文件系统仍然挂载的情况下扩展文件系统。
例如,已经扩大的 /dev/sdb1 可以通过以下命令扩展:
1 | xfs_growfs /data |
这里的 /data 必须是已经挂载的 XFS 文件系统,而且底层设备必须先具备足够的新增空间。
如果底层使用 LVM,还需要先扩展逻辑卷。xfs_growfs 不会自动扩大底层磁盘或逻辑卷。
第三,支持在线碎片整理。
XFS 提供 xfs_fsr 等工具,可以在文件系统保持挂载的情况下整理部分文件碎片。
但是,不要把它理解成必须定期运行的维护任务。SSD 上是否需要整理,要看实际碎片情况、文件访问模式和业务表现。
第四,通过元数据日志帮助恢复。
XFS 使用日志记录必要的元数据变更,以便在异常关机后恢复文件系统的一致性。
这里的日志主要是元数据日志,并不意味着所有用户数据都被完整地写入日志。
第五,不能直接缩小文件系统。
这是 XFS 一个需要提前考虑的限制。
如果你创建了一个 1 TiB 的 XFS 文件系统,后来只想保留 500 GiB,不能直接使用一个类似 resize2fs 的命令把它缩小。
通常需要备份数据、重建较小的文件系统,再恢复数据。
因此,分区规划、LVM 规划和容量预留很重要。
ext4:成熟、通用,功能同样完整
ext4 是 Linux 中非常成熟的文件系统,拥有广泛的工具支持和运维经验。
它也支持日志、延迟分配、扩展区段等机制,在许多工作负载中都能获得不错的性能。
它的主要特点包括:
- 工具成熟,排障和维护经验丰富。
- 支持在线扩容。
- 支持卸载后缩容,适合容量需要灵活调整的场景。
- 在很多常见负载下,可以达到与 XFS 相近的性能。
这里有一个容易被忽略的细节:ext4 的理论文件系统容量上限,不等于某个 RHEL 版本实际支持的容量。
例如,RHEL 10 的官方资料列出的 ext4 文件系统支持上限为 50 TiB,单个文件的支持上限为 16 TiB;ext4 的理论格式容量上限则更高。实际使用时应以操作系统版本和官方支持矩阵为准。
不要用固定的 IOPS 数字来决定文件系统
文件系统性能不仅取决于 IOPS 和带宽,还与以下因素有关:
- 文件大小和目录结构;
- 随机读写还是顺序读写;
- 线程数量与并发度;
- 同步写入的比例;
- 元数据操作频率;
- 内核版本、文件系统特性和挂载参数;
- 底层存储的延迟与缓存行为。
建议这样选:
| 场景 | 建议 |
|---|---|
| 常规 RHEL 服务器 | 优先使用 XFS |
| 大容量存储、大文件、高并发 | 优先考虑 XFS |
| 需要卸载后缩容 | 可以考虑 ext4 |
| 已有成熟的 ext4 运维规范 | 没有明确问题时不必迁移 |
| 数据库或容器存储 | 结合实际负载做基准测试 |
记住,不要为了追求某个文件系统的理论优势,就随意重建生产环境中的文件系统。 文件系统迁移涉及数据备份、停机窗口、恢复验证和业务风险,应该有明确的收益依据。
SSD 上的 discard 到底有什么用?
这是文件系统调优中一个特别容易产生误解的话题。
先看一个场景。
你的 /data 目录中有一个 100 GiB 的文件。你执行:
1 | rm -f /data/bigfile.dat |
随后查看文件系统空间:
1 | df -h /data |
你可能会发现,可供 Linux 文件系统使用的空间增加了。
但是,为什么底层 SSD 或宿主机上的虚拟磁盘文件不一定立即变小?
因为这里涉及两件不同的事情:
- 文件系统把原来属于该文件的数据块标记为空闲。
- 文件系统把这些已经不再使用的块的信息传递给底层存储。
第一件事并不保证第二件事自动发生。
discard 是什么?
discard 是一种块设备操作,用来通知底层存储:某些逻辑块已经不再需要保留原来的数据内容。
对于 SSD,这些信息可以帮助设备进行垃圾回收和磨损均衡;对于精简置备存储,它也可能帮助底层回收不再使用的空间。
不过,discard 不是简单地告诉 SSD“这些数据已经被物理擦除”,也不保证每次执行后都能立即减少宿主机磁盘占用。
Linux 有哪三种常见的 discard 方式?
方式一:手动批量丢弃
1 | fstrim /data |
它会扫描指定文件系统中符合条件的空闲区域,并向底层提交 discard 请求。
适合维护操作、批量删除数据之后,或者你想手动验证 discard 是否可用的场景。
方式二:周期性批量丢弃
Linux 可以通过 systemd 定时器定期运行 fstrim。
检查定时器状态:
1 | [root@localhost ~]# systemctl status fstrim.timer |
如果系统提供了这个定时器,但没有启用,可以执行:
1 | [root@localhost ~]# systemctl enable --now fstrim.timer |
启用后,再查看下一次触发时间:
1 | [root@localhost ~]# systemctl list-timers fstrim.timer |
需要注意,不要假设所有系统都默认启用了该定时器。先检查当前系统状态,再决定是否需要启用。
方式三:在线丢弃
在挂载文件系统时使用 discard 选项:
1 | mount -o discard /dev/sdb1 /data |
如果需要持久化配置,可以在 /etc/fstab 中对应的文件系统条目加入 discard。
在线丢弃会在文件系统释放块时提交相应的 discard 请求。不过,不同设备、文件系统和内核版本的实现细节可能不同,实际开销也会有差异。
Red Hat 对常规场景的建议是优先使用批量或周期性 discard;只有在工作负载确实需要在线丢弃时,才考虑持续启用 discard。
为什么我的 fstrim 会报错?
1 | [root@localhost ~]# fstrim /mnt |
不要直接认定是文件系统损坏。
首先检查底层设备:
1 | [root@localhost ~]# lsblk -D |
重点观察 DISC-MAX。如果底层块设备的 discard_max_bytes 为零,说明它当前没有提供可用的物理 discard 能力。
也可以直接查看:
1 | [root@localhost ~]# cat /sys/block/nvme0n1/queue/discard_max_bytes |
如果使用了 LVM、device-mapper、加密设备或者虚拟磁盘,还需要检查整条设备映射链。
例如,在 VMware 虚拟机中,即使客户机看到的是 NVMe 设备,也不意味着虚拟磁盘一定支持 discard。虚拟磁盘控制器、虚拟磁盘配置和宿主机存储都可能影响这项能力。
如果 DISC-MAX=0B,先查清楚设备为什么没有提供 discard,不要通过随意修改文件系统参数来解决。
格式化时有哪些参数值得了解?
文件系统的创建参数会影响文件系统布局和可用特性,有些参数创建后很难修改,有些则可以通过专用工具调整。
但这里要先强调一点:
格式化参数不是越多越好,也不是每个参数都能带来性能提升。
对于通用服务器,建议先使用合理的默认值。只有在明确知道工作负载、空间分布和目标收益时,才考虑特殊配置。
以下命令均为理解和实验用途。mkfs 会创建文件系统,可能破坏目标设备上已有的数据,切勿直接对生产磁盘执行。
XFS:索引节点和目录结构
先看 XFS 的索引节点大小参数:
1 | mkfs.xfs -i size=512 /dev/sdb1 |
-i size=512 指定 XFS 索引节点大小为 512 字节。在支持该配置的环境中,它决定了索引节点的大小和相关元数据空间布局。
索引节点不仅保存文件属性,还可能承载扩展属性等信息。因此,修改它并不是简单地“给元数据多留点空间”,还会影响文件系统的布局和资源开销。
对于常见服务器,默认值通常已经足够,不建议仅仅因为业务有很多小文件就随意修改。
再看目录块大小:
1 | mkfs.xfs -n size=8192 /dev/sdb1 |
-n size=8192 指定目录块大小为 8192 字节,但实际可用值还受到文件系统块大小及工具版本限制。
它并不意味着目录操作必然更快。目录查询性能还与目录项数量、目录索引、缓存命中率和实际访问模式有关。
如果没有真实测试数据,不要为了减少目录 I/O 就直接把目录块调大。
ext4:索引节点大小
ext4 可以通过 mkfs.ext4 -I 指定索引节点大小。
例如:
1 | mkfs.ext4 -I 256 /dev/sdb1 |
这里指定每个索引节点占用 256 字节。具体默认值取决于发行版和工具配置,RHEL 系列常见配置为 256 字节。
索引节点数量和大小需要结合文件系统容量、文件数量及扩展属性需求考虑。
对于小文件特别多的文件系统,索引节点布局确实值得关注,但不能简单地得出“索引节点越小越省空间、越快”的结论。
如果索引节点过小,可能影响某些扩展元数据的存储能力;而改变索引节点大小通常需要在创建文件系统时完成。
因此,除非你有明确的容量规划依据,否则优先使用发行版的默认值。
ext4 的 large_dir 和 huge_file
ext4 还有一些文件系统特性,例如 large_dir 和 huge_file。
large_dir 用于提升目录所能容纳的规模,适合目录中存在大量文件、并且目录大小已经接近相关限制的场景。
huge_file 则与支持大文件有关。它并不是一个为了减少普通小文件开销而应该随意关闭的功能。
检查当前文件系统的特性:
1 | tune2fs -l /dev/sdb1 |
如果想查看功能标志,可以重点关注 Filesystem features 字段。
不要因为业务主要存放小文件,就直接执行下面这样的命令:
1 | tune2fs -O large_dir,^huge_file /dev/sdb1 |
它不是通用的性能调优命令。修改文件系统特性可能影响兼容性、功能支持和后续挂载行为,有些操作还需要离线检查或满足特定前提。
另外,extra_isize 与 ext4 扩展索引节点字段有关。不要把它当作一个可以为了省空间而随意关闭的普通开关。
RAID 条带对齐需要手工指定吗?
XFS 提供 su、sw 等格式化参数,ext4 则有 stride 和 stripe_width 等参数,用于描述某些底层条带布局。
这些参数在特定 RAID 配置中有意义,但现代存储栈可能已经通过设备拓扑信息提供了对齐信息。
如果你使用的是硬件 RAID、SAN 或虚拟磁盘,先确认底层设备暴露出来的几何与对齐信息,不要凭经验随便填写。
对于普通 SSD 和 VMware 虚拟磁盘,优先使用合理的默认配置通常更稳妥。
挂载选项:最值得先理解的日常配置
格式化参数影响文件系统布局,而挂载选项通常可以在不重建文件系统的情况下调整。
不过,挂载选项是否适合生产环境,仍然要结合业务需求和文件系统类型判断。
atime、relatime 和 noatime
Linux 文件系统可以记录文件的访问时间,也就是 atime。
例如,你读取一个文件时,文件的访问时间可能发生更新。更新访问时间本身也会带来元数据操作。
常见选项包括:
atime:启用访问时间更新。relatime:相对访问时间更新,减少不必要的时间戳写入。noatime:不更新文件和目录的访问时间。nodiratime:不更新目录的访问时间。
在现代 Linux 中,relatime 通常是常见默认行为。它并不是每读取一次文件就必须写一次磁盘,而是根据访问时间与修改时间等条件决定是否更新。
如果业务不依赖 atime,noatime 可以进一步减少相关元数据更新。但它是否能明显提升性能,取决于工作负载。
例如,文件服务器如果大量读取文件,且访问时间记录并非业务要求,可以考虑评估 noatime;但如果某个应用依赖访问时间实现清理、归档或其他逻辑,就不能随意关闭。
查看当前挂载选项:
1 | [root@localhost ~]# findmnt -no SOURCE,FSTYPE,OPTIONS / |
不要只凭经验就把所有生产文件系统都改成 noatime。先确认业务是否依赖访问时间,再决定是否调整。
XFS 的 inode64
inode64 允许 XFS 在更广泛的文件系统地址范围内分配索引节点,而不局限于较低的磁盘地址范围。
它在大型文件系统中具有意义,能够避免旧式 inode 分配限制带来的空间分布问题。
现代 RHEL 环境中,这通常不是一个需要手动追求的性能开关。应以当前版本的默认行为和挂载信息为准。
XFS 的 logbsize
XFS 使用元数据日志记录必要的元数据变更。logbsize 可以控制内存中每个日志缓冲区的大小。
例如,在支持相应值的系统中,可以尝试:
1 | mount -o remount,logbsize=256k /data |
但这只是一个实验示例。执行之前要确认当前内核、XFS 版本和挂载选项支持该值,并且 /data 确实是 XFS 文件系统。
logbsize 不等于整个日志的大小,也不等于应用每次写入的数据块大小。
增大日志缓冲区可能改变元数据日志处理的行为,但不保证随机读 IOPS 上升,也不保证写入延迟下降。对于某些工作负载,效果可能很小,甚至没有收益。
因此,不要把 logbsize=256k 当成所有 XFS 服务器的通用最佳实践。
ext4 的 journal_ioprio
ext4 支持 journal_ioprio,用于设置日志 I/O 的优先级。
例如:
1 | journal_ioprio=3 |
该选项的具体效果与内核实现及 I/O 调度机制有关。数值越小通常表示优先级越高,但它并不是一个可以直接保证业务延迟下降的参数。
只有在明确了解当前调度机制、日志负载以及业务瓶颈的情况下,才值得考虑调整。
修改挂载选项的正确方式
先检查:
1 | findmnt /data |
如果只想临时测试某个选项,可以在确认支持后使用重新挂载的方式。
例如:
1 | mount -o remount,noatime /data |
如果需要永久生效,再修改 /etc/fstab 对应条目。
但要注意,重新挂载不代表所有选项都能随时修改,也不代表修改后一定有性能收益。涉及生产文件系统时,应先确认选项的支持情况,并安排验证和回滚方案。
用 fio 验证文件系统调优有没有效果
讲了这么多参数,最后还是要回到测试。
如果没有测试,只是把 noatime、logbsize 等选项加上,然后觉得系统变快了,这并不能证明调优有效。
因为磁盘性能还会受到以下因素影响:
- 页缓存命中率;
- 文件系统缓存与元数据缓存;
- SSD 自身的缓存和垃圾回收;
- 虚拟机调度和宿主机负载;
- 并发线程数与 I/O 队列深度;
- 文件系统空间分布和碎片情况。
安装 fio
在 RHEL 或 Rocky Linux 中,可以先检查软件包是否可用:
1 | [root@localhost ~]# dnf install fio -y |
准备独立的测试目录
先确认 /data 是你打算测试的文件系统:
1 | findmnt /data |
确保目录有足够的可用空间,并且不会影响生产业务。
创建一个专门用于测试的目录:
1 | mkdir -p /data/fio-lab |
不要把测试文件直接写到生产数据库文件、虚拟机镜像或其他真实业务数据上。
先跑一个随机混合读写测试
下面是一个示例:
1 | [root@localhost ~]# fio --name=db_test \ |
这个测试模拟的是 4 KiB 随机混合读写,读请求比例为 70%,写请求比例为 30%。
它适合用于观察文件系统和存储链路在该类负载下的表现,但不代表所有数据库的真实工作负载。
参数解释如下。
| 参数 | 含义 |
|---|---|
--directory | 测试文件所在目录 |
--filename | 测试文件名 |
--size=1G | 每个 job 的文件大小 |
--time_based | 按指定时间持续测试 |
--runtime=60 | 测试运行时间为 60 秒 |
--ramp_time=10 | 先预热 10 秒,再统计 |
--ioengine=libaio | 使用 Linux 原生异步 I/O 接口 |
--direct=1 | 使用直接 I/O,绕过普通页缓存数据路径 |
--bs=4k | 每次 I/O 的块大小为 4 KiB |
--rw=randrw | 随机混合读写 |
--rwmixread=70 | 读操作比例为 70% |
--numjobs=4 | 创建 4 个并发 job |
--iodepth=32 | 每个 job 请求队列深度目标为 32 |
--group_reporting | 汇总多个 job 的统计结果 |
需要注意,--direct=1 并不意味着绕过文件系统,也不意味着测出来的就是裸设备的绝对性能。它主要避免普通页缓存对数据读写结果的影响,文件系统元数据处理、设备缓存、虚拟化开销等仍然可能影响结果。
另外,这个命令可能会创建并写入测试文件。如果同名文件已经存在,fio 可能覆盖或改变其内容,所以一定要使用独立的测试目录和测试文件。
重点看哪些指标?
fio 输出中,建议重点关注:
IOPS:每秒完成的 I/O 操作数。
在相同块大小和相同工作负载下,IOPS 越高通常意味着处理能力越强。
BW:带宽。
表示每秒传输的数据量。大块顺序读写通常更关注带宽,而小块随机读写往往更关注 IOPS 和延迟。
clat:完成延迟。
它反映 I/O 请求从提交到完成的相关延迟统计。应同时关注平均值和百分位延迟,例如 p95、p99。
lat:总延迟。
fio 还会报告请求延迟的相关统计。具体含义要结合 fio 的输出字段、I/O 引擎和统计口径来理解。
不要只看平均延迟。如果 p99 延迟很高,意味着少量请求可能明显慢于大多数请求,这在数据库和交互型业务中尤其值得关注。
为什么不能只看 util?
很多人会把磁盘利用率当作性能好坏的直接判断依据。
实际上,设备利用率高并不一定意味着性能差,利用率低也不一定代表性能好。
例如,同样的业务负载下,如果 IOPS 提高、延迟下降,而设备利用率略有下降,这可能说明处理效率有所改善。但必须结合实际 I/O 数量、延迟、吞吐量和测试条件综合判断。
如果你希望对比文件系统参数的效果,应该尽量保持以下条件一致:
- 相同的虚拟机配置和宿主机负载;
- 相同的文件系统和测试文件大小;
- 相同的 fio 参数;
- 相同的测试时间和预热过程;
- 多次重复测试,并比较中位数或稳定趋势。
特别是在 VMware 虚拟机中,宿主机的 CPU、内存、存储缓存和其他虚拟机的负载都可能影响结果。一次测试出现 5% 的差异,并不足以证明某个挂载参数确实有收益。
文件系统调优的正确顺序
讲到这里,我们可以把整个流程串起来。
flowchart TD
A["确认业务负载"] --> B["确认文件系统类型"]
B --> C["检查存储设备与挂载选项"]
C --> D["建立 fio 基线"]
D --> E["一次只修改一个参数"]
E --> F["重复测试并比较结果"]
F --> G{"收益是否稳定?"}
G -- "是" --> H["记录配置并制定回滚方案"]
G -- "否" --> I["恢复原配置,继续定位瓶颈"]实际操作中,可以按照下面的顺序执行。
第一步:先看文件系统。
1 | findmnt -t xfs,ext4 |
确认文件系统类型、挂载点和可用空间。
第二步:检查挂载选项。
1 | findmnt -no SOURCE,FSTYPE,OPTIONS /data |
先弄清楚系统当前在用什么配置,不要在不了解默认值的情况下盲目增加参数。
第三步:确认底层存储能力。
1 | lsblk -D |
如果要使用 discard,先确认设备确实支持。
第四步:建立基准测试。
使用与业务相近的 fio 负载,记录 IOPS、带宽和延迟。
第五步:一次只改一个参数。
例如先验证 noatime 是否有收益,再单独测试其他参数。不要同时修改五六项配置,否则即使结果变好了,也很难确定到底是哪项修改起了作用。
第六步:记录结果并准备回滚。
保存测试命令、原始配置、修改后的配置和测试结果。只有收益稳定、没有引入额外风险,才值得将配置推广到生产环境。
最后总结
Linux 文件系统调优并不是把所有看起来能提升性能的参数都打开,而是理解文件系统如何管理数据、元数据和空间,然后针对具体负载验证配置。
对于大多数 RHEL 服务器,可以先记住这几条:
- 没有明确理由时,优先使用发行版默认的 XFS。
- 需要缩容、已有成熟 ext4 规范等场景,可以考虑 ext4。
- SSD 和精简置备存储需要关注 discard,但必须确认整条存储链路支持。
noatime、logbsize等参数并不是通用的性能加速开关。- 格式化参数会影响文件系统布局,不要在生产磁盘上随意试验。
- 用 fio 做可重复的基准测试,结合 IOPS、带宽和延迟判断是否真的改善。
上一篇我们聊的是 I/O 调度器,这一篇继续往上走到了文件系统。
把设备、I/O 调度器、文件系统和应用负载放在一起分析,才算真正建立起 Linux 存储性能调优的思路。
下一次遇到磁盘慢的问题,不要急着改参数。先找到瓶颈,再提出假设,最后用数据验证。这才是生产环境中最可靠的调优方法,好了,我们一起来总结一下IO方面的排查思路。
flowchart TD
A["业务出现 I/O 延迟"] --> B["检查 CPU、内存、I/O 等待"]
B --> C["iostat -xz 观察设备指标"]
C --> D["确认设备与文件系统映射"]
D --> E["检查应用 I/O 模式"]
E --> F{"主要瓶颈在哪里?"}
F -->|进程或应用| G["检查进程、同步写入与请求模式"]
F -->|块设备队列| H["检查调度器与队列参数"]
F -->|文件系统| I["检查元数据、挂载参数与空间"]
F -->|底层存储| J["检查设备延迟、宿主机与存储负载"]
H --> K["建立基准测试"]
I --> K
J --> K
G --> K
K --> L["一次修改一个参数"]
L --> M["重复测试并比较延迟、IOPS、带宽"]
M --> N{"收益稳定且风险可控?"}
N -->|是| O["记录配置并逐步应用"]
N -->|否| P["回滚并继续定位"]
P --> K