Linux 磁盘 I/O 性能诊断与存储故障排查

Linux 出现“系统很卡、CPU不高、数据库超时”时,根因可能位于应用、页缓存、文件系统、块设备、LVM、RAID、虚拟化存储、HBA、网络存储或物理磁盘。本文给出一套从症状到设备的分层诊断方法,避免只看到 iowait 就判断磁盘坏了。

压测工具会产生真实读写。fio、丢弃、文件系统修复、RAID 重建和块设备写测试禁止在未知生产盘直接执行。

一、建立I/O路径

应用 read/write/fsync
  ↓
VFS与页缓存
  ↓
文件系统 ext4/xfs
  ↓
dm-crypt / LVM / multipath / mdraid
  ↓
块层队列与调度器
  ↓
驱动、HBA、虚拟磁盘或网络存储
  ↓
SSD/NVMe/HDD/存储阵列

故障定位要回答:

  • 是读慢、写慢还是 fsync 慢;
  • 是吞吐不足、IOPS 不足还是尾延迟升高;
  • 是所有进程还是单个进程;
  • 是单盘、单路径、单主机还是共享存储全局;
  • 是持续问题还是定时任务触发;
  • 是设备服务时间变慢,还是上层排队过多。

二、先采集基线

uptime
vmstat 1
mpstat -P ALL 1
pidstat -dru 1
iostat -xz 1
lsblk -o NAME,KNAME,TYPE,SIZE,FSTYPE,MOUNTPOINTS,ROTA,SCHED,MODEL,SERIAL
findmnt
df -hT
df -ih

同时保存内核日志:

journalctl -k --since '-2 hours'
dmesg -T | grep -Ei 'error|timeout|reset|abort|I/O|nvme|scsi|blk|ext4|xfs'

不要只截一秒数据。至少覆盖正常、异常和恢复阶段,并记录同一时间的业务吞吐。

三、正确理解iowait

wa 表示 CPU 空闲且至少有任务在等待 I/O 的时间比例。它不是磁盘利用率,也不能说明具体设备。CPU 很忙时,即使 I/O 很慢,iowait 也可能不高;系统只有少量 CPU 时,一条同步 I/O 也可能让比例看起来很高。

判断必须结合:

  • 应用延迟和吞吐;
  • 设备延迟和队列;
  • 进程 I/O;
  • 文件系统与内核错误;
  • 存储后端指标。

四、阅读iostat关键字段

iostat -xz 1

不同版本字段略有差异,重点理解:

  • r/s、w/s:每秒请求数;
  • rkB/s、wkB/s:吞吐;
  • await:请求从提交到完成的平均时间,包含排队;
  • r_await/w_await:读写延迟;
  • aqu-sz:平均队列长度;
  • %util:设备处理 I/O 的时间比例。

NVMe、阵列和并行设备即使 %util=100 仍可能继续处理更多 I/O;机械盘则更容易饱和。应以延迟、队列和业务 SLO 判断,而不是把 %util 当作统一红线。

五、定位产生I/O的进程

pidstat -d 1
iotop -oPa
cat /proc/<pid>/io
lsof -p <pid>

关注:

  • read_bytes/write_bytes:真正触发的存储 I/O;
  • rchar/wchar:系统调用层处理字节,可能命中缓存;
  • cancelled_write_bytes:写入后又被截断或删除;
  • 进程是否频繁 fsync;
  • 是否由日志、备份、压缩、扫描、数据库 checkpoint 触发。

容器环境还要从宿主机、cgroup 和容器进程三个视角关联,避免只看容器内的虚拟设备。

六、页缓存与脏页

free -h
grep -E 'Dirty|Writeback|Cached|Buffers|MemAvailable' /proc/meminfo
vmstat 1
sysctl vm.dirty_ratio vm.dirty_background_ratio
sysctl vm.dirty_bytes vm.dirty_background_bytes

大量写入先进入页缓存,后台回写跟不上时,脏页持续增长;达到阈值后,应用可能被迫参与回写,出现周期性延迟尖峰。

治理顺序:

  1. 找到写入来源;
  2. 检查设备写入能力和延迟;
  3. 观察脏页增长与回落;
  4. 调整应用批量、日志和 checkpoint;
  5. 最后才根据内存和存储特性调整 dirty 参数。

不要在没有压测时盲目增大 dirty 阈值,它可能让更大的写入洪峰集中落盘。

七、同步写与fsync延迟

数据库和关键日志常依赖 fsync 保证持久化。吞吐看似正常,但单次落盘延迟升高就会放大事务提交时间。

可使用应用指标、数据库 WAL 指标、strace 短时采样或 eBPF 工具观察:

strace -ttT -p <pid> -e trace=fsync,fdatasync,read,write,pread64,pwrite64

strace 会带来开销,只应短时、针对单进程使用。更低干扰的环境可用 bcc/bpftrace 的 biolatency、biosnoop、fileslower 等工具。

八、文件系统检查

findmnt -o TARGET,SOURCE,FSTYPE,OPTIONS
df -hT
df -ih
xfs_info <mountpoint>
tune2fs -l /dev/<device> 2>/dev/null

常见问题:

  • 容量满或 inode 用尽;
  • 文件删除但进程仍持有;
  • 只读重挂载;
  • ext4 journal 或 XFS 元数据错误;
  • 大量小文件导致目录和元数据压力;
  • 挂载参数不合适;
  • 快照或 reflink 导致空间判断复杂。

查找已删除但仍占空间的文件:

lsof +L1

应通过安全地重载、轮转或重启对应进程释放句柄,不要直接操作 /proc/<pid>/fd 下未知描述符。

九、LVM、Device Mapper与快照

pvs
vgs
lvs -a -o +devices,segtype,data_percent,metadata_percent
dmsetup ls --tree

LVM thin pool 的 data 或 metadata 满都可能导致 I/O 失败。传统快照空间耗尽会失效;大量快照还会增加写放大。必须对 thin pool 数据、元数据、快照增长和自动扩容分别告警。

十、软件RAID

cat /proc/mdstat
mdadm --detail /dev/mdX

RAID 降级后仍可服务不代表安全。重建期间负载、温度和读取压力升高,另一块老盘可能继续失败。更换前核对序列号和槽位,重建时观察速度、错误和业务延迟。

RAID 不是备份,控制器缓存也必须有断电保护和可监控的电池/电容状态。

十一、NVMe与SSD健康

nvme list
nvme smart-log /dev/nvme0
smartctl -x /dev/nvme0

重点包括:

  • critical warning;
  • media/data integrity errors;
  • available spare;
  • percentage used;
  • unsafe shutdowns;
  • temperature;
  • error log;
  • 固件和 PCIe 链路状态。

SSD 延迟也可能因温度降速、垃圾回收、SLC 缓存耗尽、写放大或固件问题突然升高。健康百分比不是唯一判据。

十二、SATA/SAS/HDD与HBA

smartctl -x /dev/sdX
lsscsi -g

关注重新分配扇区、待处理扇区、不可校正错误、CRC、命令超时、介质和非介质错误。CRC 增长可能来自线缆、背板或 HBA,而非盘片。

内核出现 reset、abort、link down、I/O error 时要保存完整时间线,并关联控制器日志、阵列事件和机房操作。

十三、Multipath与SAN

multipath -ll
multipathd show paths
multipathd show maps

检查路径状态、优先级、策略和队列。queue_if_no_path 在所有路径丢失时可能让应用无限挂起;是否启用要由业务超时与恢复策略决定。

SAN 问题需要同时查看主机 HBA、交换机端口、阵列前端口、LUN 和存储池。单看 Linux 设备无法发现后端热点或控制器故障。

十四、NFS与分布式文件系统

nfsstat -m
nfsiostat 1
mountstats

网络文件系统的“磁盘慢”可能是 DNS、网络丢包、服务端负载、锁、挂载参数或元数据热点。检查请求重传、RTT、执行时间以及服务端磁盘,避免只在客户端调块设备参数。

十五、块层调度器与队列

cat /sys/block/<device>/queue/scheduler
cat /sys/block/<device>/queue/nr_requests
cat /sys/block/<device>/queue/read_ahead_kb

调度器选择与设备类型、虚拟化层和工作负载相关。数据库随机 I/O、大文件顺序读、桌面交互和共享阵列的最佳设置不同。调整前记录延迟分布和吞吐,调整后用真实业务回放验证。

十六、安全使用fio

只在独立测试文件或明确的测试盘上运行:

fio --name=randread --filename=/safe-test-path/fio.test \
  --size=2G --rw=randread --bs=4k --iodepth=32 \
  --ioengine=libaio --direct=1 --runtime=60 --time_based \
  --group_reporting

生产验证要区分:

  • 随机/顺序;
  • 读写比例;
  • 块大小;
  • 队列深度和并发作业;
  • buffered/direct;
  • 平均延迟和 P95/P99/P999;
  • 是否命中阵列缓存。

不要用超高队列深度制造漂亮 IOPS,却忽略业务真实尾延迟。

十七、常见故障处置

磁盘空间满

检查文件、inode、已删除句柄、日志、容器层、快照和数据库 WAL。先阻止继续增长,再安全释放或扩容。不要对数据库目录直接删除未知文件。

设备延迟突增

保存 iostat、进程 I/O、内核日志和后端存储指标;确认是否故障盘、路径切换、重建、备份或批任务;必要时限流非关键任务,避免重启丢失现场。

文件系统只读

读取内核错误并保护数据;确认底层设备是否仍稳定;在维护窗口卸载并按文件系统官方流程检查。在线强制修复可能扩大损坏。

云盘性能不足

核对规格的 IOPS、吞吐、突发积分和实例带宽上限;监控节流;区分本地系统队列与云平台限制。扩盘不一定自动提高文件系统和逻辑卷容量,也不一定立刻提升性能。

十八、监控清单

  • 容量、inode、增长率和已删除句柄;
  • 吞吐、IOPS、队列和读写延迟分位数;
  • fsync/数据库提交延迟;
  • iowait、阻塞任务和进程 I/O;
  • 脏页、回写和内存压力;
  • 文件系统错误和只读事件;
  • RAID、Multipath、SAN/NFS 路径;
  • SMART/NVMe 健康、温度和介质错误;
  • 云盘节流或阵列缓存状态;
  • 备份、快照和重建对业务的影响。

十九、结语

I/O 排障的关键不是记住某个阈值,而是把应用请求沿数据路径逐层拆开,分清设备服务慢、上层排队、缓存回写和后端限流。先保存证据并保护数据,再降低负载或切换路径,最后通过真实工作负载验证治理效果。

参考资料

Copyright © yan-jian.com 2023 - 2026 · Powered by GitBook更新时间: 2026-10-28 21:12:04

results matching ""

    No results matching ""