iostat 和 iotop:诊断 Linux 存储瓶颈

14 分钟阅读 - 2026年6月12日

hero section cover
目录
  • iostat 和 iotop:诊断 Linux 存储瓶颈
  • 安装 iostat 和 iotop
  • 阅读 iostat 输出
  • 解读 iotop 输出
  • 诊断工作流
  • 解决常见的 I/O 瓶颈
分享

使用 iostat 和 iotop 查找 Linux 磁盘 I/O 瓶颈。涵盖 NVMe、读取等待和队列深度的 %util 故障,以及查找和修复故障的工作流程。

iostat 和 iotop:诊断 Linux 存储瓶颈

当 Linux 服务器运行缓慢时,存储是首要排查的环节之一。iostat 可显示磁盘是否处于过载状态;iotop 则能指出哪个进程正在造成负载。两者结合使用,可解答两个关键问题:磁盘是否确实是瓶颈?如果是,究竟是什么在对其造成巨大压力? 本文涵盖了安装方法、如何解读输出结果(包括 iostat 的 %util 指标在现代硬件上的位置),以及从症状到修复的完整工作流程。

安装 iostat 和 iotop

iostat 随 sysstat 包一同提供;iotop 则单独发布。请同时安装两者:

# Debian/Ubuntu
sudo apt install sysstat iotop
 
# RHEL, AlmaLinux, Rocky, CentOS Stream
sudo dnf install sysstat iotop
 
# Arch
sudo pacman -S sysstat iotop

在 Ubuntu 系统中,sysstat 默认处于禁用状态。若要收集后台数据以便后续使用 sar,请编辑 /etc/default/sysstat,将 ENABLED="true",并重启服务:

sudo systemctl restart sysstat

iotop 必须以 root 身份运行。在 RHEL 9 及更高版本中,延迟计费功能默认处于禁用状态,这会导致 IOSWAPIN 列为空。请使用以下命令启用:

echo 1 | sudo tee /proc/sys/kernel/task_delayacct

添加 kernel.task_delayacct = 1/etc/sysctl.conf ,使其在重启后仍保持生效。

阅读 iostat 输出

运行 iostat 并启用扩展统计功能,忽略第一个样本(该样本仅显示自系统启动以来的平均值):

iostat -xz 2

使用 -x 标志会添加扩展统计信息, -z 隐藏空闲设备,且 2 每两秒刷新一次。关键列包括:

  • await:I/O 请求完成所需的平均时间(以毫秒为单位),包含队列等待时间。当用户抱怨系统运行缓慢时,这是最重要的指标。
  • r/s 以及 w/s:读写 IOPS。结合 rkB/swkB/s 这些指标,可判断工作负载是随机型(高 IOPS、低吞吐量)还是顺序型(低 IOPS、高吞吐量)。
  • aqu-sz:平均队列深度。对于 HDD,若该值持续高于 1,则表示磁盘无法跟上处理速度。
  • %util:设备处于至少有一个进行中 I/O 状态的时间占比。对 HDD 有参考价值,但对 NVMe 可能具有误导性(见下文)。

快速阈值参考:

磁盘类型关注点队列深度关注点%util 是否可靠?
7200 RPM 硬盘> 20 毫秒> 1
SATA固态硬盘> 10 毫秒> 4大部分
NVMe> 1-2 毫秒> 16

%util 所在的位置

%util 是大多数人首先关注的指标,但在 NVMe 上,这个指标实际上具有误导性。内核将 %util “任何时刻正在进行的 I/O”,这对一次只处理一个请求的机械硬盘来说没问题,但对于在硬件队列中并行处理数千个请求的 NVMe 设备来说毫无意义。一块 NVMe 驱动器可能显示 100% %util ,实际利用率却仅为5%。

在 NVMe 环境中,请相信 r_await, w_awaitaqu-sz 。如果 r_await 始终保持在1毫秒以内,且队列深度远低于设备的硬件队列深度(通常为1024或更高),那么无论 %util 显示什么。

若需以 MB/s 而非 kB/s 查看高速 NVMe 性能:

iostat -xm 1

若需长期收集数据,后续可与应用程序日志进行关联分析:

iostat -x -t 5 720 > /var/log/iostat.log

这会以每 5 秒为间隔采样一小时。 sar 来自同一 sysstat 包的数据可提供具有持久历史存储功能的等效数据,是持续监控的更佳选择。

通过 CPU iowait 进行验证

如果 iostat 显示存储压力,请与 %iowait 同一输出顶部 CPU 摘要中的 iowait 列进行交叉核对。持续 %iowait 持续高于 15-20%,加上 await 则可确认瓶颈在于存储。如果 %iowait 该值较高但 await 看起来正常,请运行 vmstat 1 并检查 siso 列。非零的交换活动意味着系统受内存限制,且磁盘流量属于分页操作,而非应用程序 I/O。

解读 iotop 输出

一旦 iostat 确认存在存储瓶颈,iotop 会指出是哪个进程导致的。请从以下命令开始:

sudo iotop -o

使用 -o 参数可隐藏空闲进程,仅保留正在进行 I/O 操作的进程。需关注的列:

  • DISK READ / DISK WRITE:每个进程的实时吞吐量。可识别明显的I/O消耗大户。
  • IO:进程因 I/O 阻塞所占的时间百分比。如果某个进程仅以 50 kB/s 的速度写入数据,但频繁进行微小的同步 fsync() 调用,即使写入速度仅为 50 kB/s,其 I/O 阻塞率仍可能高达 99%。该列比原始吞吐量更具参考价值。
  • SWAPIN:等待交换页的时间占比。此处非零值意味着系统正在进行分页,而您的“存储问题”实际上是内存问题。

对于多线程应用程序(如 MySQL、PostgreSQL、Java 工作负载),请使用 -P,并加上 -a 来累积自 iotop 启动以来的总和:

sudo iotop -oPa

使用 -a 标志是捕捉突发性工作负载(如备份任务)的关键,这类任务每次仅运行几秒钟,否则在实时视图中很难察觉。

若需在无人值守的夜间时段进行自动日志记录:

sudo iotop -botqq -d 10 > /var/log/iotop.log

这将每 10 秒写入一个非交互式快照。将其与备份或 cron 任务的时间戳结合使用,事后即可找出肇事者。

诊断工作流

大多数磁盘 I/O 排查都遵循相同的步骤:

  1. iostat -xz 2 确认磁盘是否确实是瓶颈。查看 await, aqu-sz,以及 %iowait。如果这些指标正常,问题就不在存储端,你应该完全去其他地方寻找原因。
  2. iotop -oPa 找出引发负载的进程。请重点关注 I/O 列,而非吞吐量列。最严重的罪魁祸首通常是执行大量小规模同步写入的程序,而非传输数据量最大的程序。
  3. lsof -p <pid> 查看该进程正在操作哪些文件。这通常能立即识别出工作负载的类型:数据库写入前日志、应用程序日志文件、备份挂载点或临时文件。

有两个模式值得了解。

如果你看到类似 jbd2/... (ext4 日志) 或 txg_sync (ZFS) 这类内核线程,它们只是响应其他进程的写入请求,而非发起者。真正导致日志流量的用户空间进程才是根本原因;请继续深入排查。

在 VPS 上,高 await 且低 %util 是典型的“噪音邻居”信号。另一位租户正在独占共享存储,导致你的 I/O 请求在 hypervisor 端排队,而非在你的虚拟磁盘上。你可以在虚拟机内部确认但无法解决此问题;解决方法是向服务商升级问题,或者迁移到配备隔离存储的服务器。

解决常见的 I/O 瓶颈

一旦确定了导致磁盘负载的原因,解决方法通常很简单。

降低非关键 I/O 的优先级。 ionice 将进程置于空闲调度类中,该类仅在无其他进程争用时才使用磁盘带宽:

ionice -c 3 -p <pid>
sudo ionice -c 3 rsync -a /data /backup

第一种形式用于修改正在运行的进程;第二种形式则会启动一个已处于空闲调度类中的新进程。在 iotop 中,您可以通过按 i 键交互式地更改正在运行的进程的优先级。

将高频工作负载迁移至更快的存储设备。如果 iostat 显示 SATA 硬盘因数据库写入而过载,且同一服务器内有闲置的 NVMe 设备,请将数据库数据目录迁移至 NVMe 设备。IOPS 数量级的差异使得此举成为当前最具成本效益的解决方案。

设置正确的 I/O 调度器。现代内核的默认设置通常合理,但仍值得检查。对于 NVMe 和 SSD,请将调度器设置为 none。该设备在硬件层面的队列处理能力优于内核:

echo none > /sys/block/nvme0n1/queue/scheduler

对于处理混合工作负载的 HDD, mq-deadline 通常是首选方案。

使用 noatime 挂载。默认情况下,每次读取都会更新文件的最后访问时间戳,导致每次读取都产生一次写入操作。在读取密集型文件系统中,这属于不必要的 I/O。将 noatime 到挂载选项中 /etc/fstab:

UUID=... /data ext4 defaults,noatime 0 2

针对突发性写入调整写回策略。在内存充足的服务器上,默认的脏页阈值会导致页面缓存积累数GB的未写入数据,随后一次性大量刷新。降低 /etc/sysctl.conf 中的阈值以平滑这一过程:

vm.dirty_ratio = 10
vm.dirty_background_ratio = 5

磁盘本身通常不是问题所在。当 iostat 显示 IOPS 很高而吞吐量很低时,说明工作负载正在对本可顺序处理的数据进行随机 I/O,或者在执行许多本可批量处理的小写入操作。在归咎于硬件之前,请先检查应用程序。

若您在网络性能远超磁盘的服务器上运行存储密集型工作负载,FDC 基于 NVMe 的专用服务器将为您提供充足的性能余量,助您高效实施上述调优方案。

博客

本周特色

更多文章
优化 Linux 服务器工作负载的调整配置文件

优化 Linux 服务器工作负载的调整配置文件

如何为 GPU、数据库和高带宽 Linux 服务器选择、应用和定制经过调整的配置文件,并提供示例和 Ansible 部署技巧。

16 分钟阅读 - 2026年6月9日

VPS 的 Linux OOM 杀手调整:实用指南

12 分钟阅读 - 2026年6月8日

更多文章