Linux系统排查3——I/O篇

在Linux系统中,I/O(输入/输出) 是系统性能的核心瓶颈点之一。无论是数据库服务、日志系统、大数据处理,还是普通的Web应用,I/O性能都会直接影响系统的响应速度和稳定性。例如:

  • 数据库(如MySQL)的频繁读写会导致磁盘I/O压力陡增;
  • 日志服务(如ELK)的高并发写入可能造成磁盘队列积压;
  • 硬件老化或故障会导致I/O响应时间飙升,进而引发系统卡顿。

掌握I/O问题的排查方法,是运维、开发人员的必备技能。本文将从基础概念、工具实战、排查流程、常见场景和最佳实践五个维度,详细讲解Linux系统I/O问题的定位与优化。

目录#

I/O基础概念#

1. I/O的核心指标#

  • 吞吐量(Throughput):单位时间内的I/O数据量(如kB/s)或操作数(如IOPS,每秒I/O操作次数)。
  • 响应时间(Latency):I/O请求从发起到完成的时间(如await,平均响应时间,单位ms)。
  • 队列长度(Queue Length):等待处理的I/O请求数量(如avgqu-sz,平均队列长度)。
  • 设备利用率(%util):磁盘处于“忙碌”状态的时间占比,接近100%时说明磁盘饱和。

2. I/O的层级模型#

Linux的I/O流程从用户空间到内核空间,再到块设备层,最终到物理磁盘:

  1. 用户进程发起I/O请求(如read()/write())。
  2. 请求通过系统调用进入内核,由文件系统(如Ext4、XFS)处理。
  3. 内核将请求转发到块设备层(block layer),并维护I/O队列。
  4. 块设备驱动(如sd_mod)与物理磁盘(HDD/SSD)交互,完成实际读写。

常用I/O排查工具#

1. iostat:磁盘I/O统计#

iostat属于sysstat工具集,用于监控磁盘和CPU的I/O统计信息。

功能与参数#

  • 核心参数:-x(扩展输出,含详细I/O指标)、-d(仅显示磁盘)、-k(单位KB)、-t(显示时间)、interval count(间隔秒数+采集次数)。

示例与输出解读#

执行 iostat -xdk 1 2(每秒采集1次,共2次,单位KB,扩展输出):

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.00    0.00    0.00    5.00    0.00   95.00
 
Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     0.00    0.00   10.00     0.00    40.00     8.00     0.05    5.00    0.00    5.00   0.50   0.50
  • rrqm/s/wrqm/s:每秒合并的读/写请求数(内核优化,合并小请求提升效率)。
  • r/s/w/s:每秒读/写操作次数(IOPS的读/写拆分)。
  • rkB/s/wkB/s:每秒读/写数据量(吞吐量)。
  • avgrq-sz:平均每个I/O请求的大小(单位:扇区,1扇区=512字节。示例中8.00扇区=4KB,与wkB/s=40、w/s=10的关系:40/10=4KB,验证一致)。
  • avgqu-sz:平均I/O队列长度(示例中0.05,表示队列中平均有0.05个请求等待)。
  • await:平均响应时间(含队列等待+实际服务时间,示例中5.00ms)。
  • svctm:实际服务时间(内核已不再维护该指标的准确性,仅作参考)。
  • %util:磁盘忙碌时间占比(示例中0.50%,表示磁盘仅5‰的时间在工作)。

2. iotop:进程级I/O监控#

iotop类似top,按进程维度展示I/O活动,适合定位“谁在消耗I/O”。

功能与参数#

  • 核心参数:-o(仅显示有I/O的进程)、-P(显示PID而非TID)、-u <user>(仅显示指定用户的进程)。

示例与输出解读#

执行 iotop -o(仅显示有I/O的进程):

Total DISK READ :       0.00 B/s | Total DISK WRITE :      40.00 KB/s
Actual DISK READ:       0.00 B/s | Actual DISK WRITE:      40.00 KB/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND
  1234 be/4 root        0.00 B/s    40.00 KB/s  0.00 %  0.50 % java -jar app.jar
  • DISK READ/WRITE:进程的逻辑I/O(含页缓存命中的读写,不一定是物理磁盘操作)。
  • Actual DISK READ/WRITE:实际物理磁盘的读写(受页缓存影响,通常小于DISK列)。
  • IO>:进程等待I/O完成的时间占比,高值说明进程因I/O阻塞。

▶ 3. vmstat:系统整体I/O与CPU#

vmstat监控系统整体状态(内存、CPU、I/O、进程),适合快速判断系统瓶颈。

功能与参数#

  • 核心参数:interval count(间隔秒数+采集次数)。

示例与输出解读#

执行 vmstat 1 5(每秒采集1次,共5次):

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 786944  84504 201568    0    0     0     0   94  199  0  0 100  0  0
 0  0      0 786944  84504 201568    0    0     0    40   93  198  0  0  99  1  0
  • bi/bo:块设备的读入/写出速率(单位KB/s),示例中bo=40表示每秒写出40KB。
  • wa:CPU等待I/O完成的时间占比(示例中wa=1%,说明CPU有1%的时间在等I/O)。
  • r/b:运行/阻塞的进程数,b>0表示有进程因I/O阻塞。

▶ 4. dmesg:内核I/O日志#

dmesg查看内核环形缓冲区,可捕捉硬件或驱动的I/O错误(如磁盘超时、坏道)。

示例与输出解读#

执行 dmesg | grep -i error 或 dmesg | grep sda(过滤磁盘sda的日志):

[  +0.000000] sd 0:0:0:0: [sda] tag#0 FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_TIMEOUT
[  +0.000000] blk_update_request: I/O error, dev sda, sector 8 op 0x0:(READ) flags 0x80700
  • 日志中的DRIVER_TIMEOUT表示磁盘I/O超时,I/O error表示读写失败,需结合硬件检测(如smartctl)进一步排查。

▶ 5. fio:I/O性能测试#

fio是强大的I/O性能测试工具,可模拟不同负载(随机/顺序、读/写、不同队列深度)。

示例:随机写测试#

执行以下命令,模拟16个并发I/O请求、4KB块大小、随机写、1GB文件的负载:

fio --name=randwrite \
    --ioengine=libaio \    # I/O引擎(libaio为异步I/O)
    --iodepth=16 \         # 队列深度(并发I/O数)
    --rw=randwrite \       # 随机写
    --bs=4k \              # 块大小
    --size=1G \            # 文件大小
    --numjobs=1 \          # 进程数
    --runtime=60 \         # 运行时间(秒)
    --group_reporting      # 聚合输出

输出解读(关键指标)#

write: IOPS=745, BW=2982KiB/s (3054kB/s)(179MiB/60001msec)
clat (msec): min=0, max=100, avg=21.45, stdev=10.32  # 完成延迟(含队列等待)
lat (msec)   : 2=0.01%, 4=0.02%, 10=10.00%, 20=50.00%  # 延迟分布(90%请求在20ms内完成)
  • IOPS:每秒I/O操作数(示例中745,即每秒完成745次4KB写操作)。
  • BW:吞吐量(示例中2982KiB/s ≈ 745 IOPS × 4KB)。
  • clat:完成延迟(从请求提交到完成的时间),avg=21.45ms说明平均响应时间为21.45毫秒。

I/O问题排查流程#

1. 问题发现#

通过监控系统(如Zabbix、Prometheus)或应用反馈(如“系统卡顿”“数据库查询慢”)发现I/O异常。

2. 采集指标#

  • 整体磁盘:iostat -x 1 5 → 关注%util、await、r/s/w/s、rkB/s/wkB/s。
  • 系统整体:vmstat 1 5 → 关注bi/bo、wa、r/b。
  • 进程级:iotop -o → 定位高I/O进程(如java、mysql)。

3. 分析瓶颈#

  • 磁盘饱和:%util > 90%且await远大于svctm(如await=50ms,svctm=5ms),说明I/O请求排队。
  • CPU等I/O:wa > 10%且bi/bo持续高位,说明CPU因I/O阻塞(如磁盘慢或请求过多)。
  • 进程异常:iotop中某进程的DISK WRITE持续>10MB/s,需排查是否为日志刷屏、数据库疯狂写入等。

4. 定位根因#

  • 硬件/驱动:dmesg | grep -i error → 检查磁盘超时、坏道(如DRIVER_TIMEOUT、I/O error)。
  • 文件系统:df -h(空间)、df -i(inode)→ 排查空间/inode不足;xfs_repair(XFS)或e2fsck(Ext4)修复文件系统。
  • 应用逻辑:结合进程(如java)的业务日志,排查是否为代码Bug(如循环写日志)。

5. 优化或测试#

  • 系统调优:调整I/O调度器(如SSD用mq-deadline)、预读大小(read_ahead_kb)。
  • 应用优化:缓存(如Redis)、批量写入(如数据库batch insert)、异步I/O(如Java NIO)。
  • 硬件升级:HDD换SSD(提升随机I/O)、扩容RAID(提升吞吐量)。

常见I/O问题场景#

1. 磁盘I/O瓶颈#

现象#

  • iostat显示%util=98%、await=100ms(正常<10ms),应用响应超时。
  • vmstat显示wa=20%、bo=100MB/s(持续高写)。

原因与处理#

  • 磁盘性能不足:HDD的随机I/O性能差(IOPS≈100),换SSD(IOPS≈10万)。
  • 请求过多:数据库(如MySQL)的innodb_flush_log_at_trx_commit=1导致频繁刷盘,调整为2(异步刷盘)。

2. 进程异常I/O#

现象#

  • iotop中某python进程的DISK WRITE=50MB/s,写入/tmp大量小文件。

原因与处理#

  • 代码Bug:脚本循环生成临时文件(如未加sleep的日志生成器),修复逻辑或加限流。
  • 恶意程序:挖矿病毒疯狂写磁盘,kill进程并清理病毒。

3. 硬件/驱动故障#

现象#

  • dmesg报DRIVER_TIMEOUT、I/O error,系统日志提示“磁盘sda坏道”。

原因与处理#

  • 磁盘坏道:smartctl -a /dev/sda → 检查SMART信息,坏道过多则更换磁盘。
  • 驱动不兼容:升级内核或块设备驱动(如sd_mod)。

I/O优化最佳实践#

1. 监控与告警#

  • 指标采集:用node_exporter+Prometheus采集iostat、vmstat指标,可视化(如Grafana)。
  • 告警阈值:%util>90%、await>50ms、wa>15%时告警。

2. 系统参数调优#

  • I/O调度器:
    • SSD:echo mq-deadline > /sys/block/sda/queue/scheduler(多队列,低延迟)。
    • HDD:echo bfq > /sys/block/sda/queue/scheduler(公平队列,适合机械盘)。
  • 预读大小:echo 16384 > /sys/block/sda/queue/read_ahead_kb(SSD设为16-32KB,HDD设为128-256KB)。

3. 硬件与存储优化#

  • 磁盘选型:随机I/O密集型(如数据库)用SSD;顺序I/O密集型(如日志)用HDD+RAID。
  • RAID优化:写密集型用RAID10(高读写),读密集型用RAID5(高容量)。

4. 应用层优化#

  • 缓存:用Redis、Memcached缓存热点数据,减少磁盘读。
  • 批量I/O:数据库INSERT改为batch insert,日志flush改为异步(如logback的AsyncAppender)。

总结#

Linux I/O问题的排查需结合工具链(iostat/iotop/vmstat/dmesg/fio)和流程化分析:

  1. 从“整体”(系统/磁盘)到“局部”(进程/硬件)定位瓶颈;
  2. 结合指标(%util/await/wa)和日志(dmesg)分析根因;
  3. 通过调优(系统/应用/硬件)或测试(fio)验证优化效果。

多在测试环境模拟真实负载(如fio压测),熟悉工具输出和系统行为,才能在生产环境快速响应I/O故障。

参考资料#

  1. 《Linux性能优化权威指南》(极客时间)
  2. iostat/iotop/vmstat/fio的官方Man手册(man iostat等)
  3. Red Hat Enterprise Linux性能调优指南(https://access.redhat.com/documentation)
  4. 阿里云开发者社区:《Linux系统I/O性能优化实战》

通过本文的工具实战和流程指导,希望你能掌握Linux I/O问题的排查与优化方法,让系统告别“卡顿”,稳定运行!