1. 项目概述:为什么我们需要关注磁盘IO?
在Linux服务器运维、性能调优甚至是日常开发排查线上问题的过程中,磁盘IO(Input/Output,输入/输出)性能往往是那个最容易被忽视,却又在关键时刻“卡脖子”的关键因素。你可能遇到过这样的场景:应用响应突然变慢,CPU和内存使用率看起来都挺正常,但系统就是“卡顿”得不行。或者,数据库查询耗时飙升,前端页面加载缓慢,一通排查下来,最后发现瓶颈竟然在磁盘读写上。这时候,如果不会查看和分析磁盘IO使用情况,就像医生不会看X光片,只能干着急。
“linux查看磁盘io使用情况”这个标题,看似简单,背后却涵盖了从基础监控到深度性能分析的一整套方法论。它不仅仅是敲几个命令看看数字那么简单,更重要的是理解这些数字背后的含义:你的磁盘是“闲得发慌”还是“忙到冒烟”?是顺序读写还是随机读写占主导?IO延迟有多高?有没有进程在“疯狂”读写磁盘?搞清楚这些,才能对症下药,无论是优化应用代码、调整文件系统参数、升级硬件还是做架构层面的拆分,都有了科学的依据。对于系统管理员、运维工程师、后端开发者乃至任何需要与服务器打交道的技术人员来说,这都是必须掌握的核心技能。
2. 核心工具与命令全解析
Linux生态提供了从简单到复杂、从实时到历史记录的一系列工具来满足不同场景下的IO监控需求。我们可以把它们分为几个层次:实时查看、进程级监控、历史统计和性能压测。
2.1 实时监控利器:iostat
iostat可能是最常用、信息最全面的磁盘IO实时监控工具,它属于sysstat工具包。它的强大之处在于,不仅能看磁盘,还能看CPU,并且提供了丰富的速率和延迟指标。
安装与基础使用大多数Linux发行版默认没有安装sysstat,需要手动安装:
# CentOS/RHEL/Fedora sudo yum install sysstat # Debian/Ubuntu sudo apt-get install sysstat安装后,最简单的用法是iostat,但它默认显示的是自系统启动以来的平均值,对实时监控意义不大。我们更常用的是带时间间隔的用法:
iostat -dx 2 5这个命令的含义是:以-d显示设备(磁盘)统计信息,-x显示扩展统计信息(这是关键),每2秒刷新一次,总共刷新5次后退出。
关键指标解读执行命令后,你会看到类似下面的输出(这里以sda设备为例):
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util sda 5.20 3.10 256.00 128.00 0.00 0.00 0.00 0.00 1.20 2.50 0.05 49.23 41.29 0.80 0.66这些指标乍一看很多,但我们可以分组理解:
- 吞吐量(Throughput):
r/s,w/s:每秒的读、写请求次数(IOPS)。这是衡量磁盘处理能力的关键。rkB/s,wkB/s:每秒读、写的数据量(KB)。这反映了数据流量的大小。
- 队列与合并:
rrqm/s,wrqm/s:每秒被合并的读、写请求数。合并相邻的IO请求能提升效率。%rrqm,%wrqm:被合并的读、写请求百分比。比例高通常是好事,说明IO模式比较连续。
- 延迟(Latency):
r_await,w_await:读、写请求的平均等待时间(毫秒)。这是最关键的体验指标,直接决定了应用程序感受到的“快慢”。通常,机械硬盘应在10ms以内,SSD应在1ms以内。如果这个值持续很高,说明磁盘响应慢。aqu-sz:平均请求队列长度。如果这个值持续大于1,说明IO请求经常需要排队。
- 请求大小:
rareq-sz,wareq-sz:读、写请求的平均大小(扇区,通常1扇区=512字节)。小文件随机读写会导致这个值很小。
- 利用率与繁忙度:
svctm:平均每次IO请求的服务时间(毫秒)。这个值在单磁盘上接近物理极限(如机械盘寻道时间)。%util:设备带宽利用率百分比。这是最经典的“磁盘忙不忙”的指标。但要注意,对于SSD或RAID阵列,由于并行处理能力,即使%util达到100%,也不一定意味着饱和,需要结合r_await/w_await和aqu-sz一起看。
实操心得:不要孤立地看
%util。一个%util接近100%但r_await很低(如<1ms)的SSD,可能依然游刃有余。而一个%util只有70%但r_await高达几十毫秒的机械硬盘,很可能已经遇到了瓶颈(比如磁头频繁寻道)。我的习惯是,先看r_await/w_await判断用户体验,再看%util和aqu-sz判断设备压力,最后用r/s/w/s和rkB/s/wkB/s分析负载类型。
2.2 进程级IO追踪:iotop与pidstat
知道了磁盘忙,下一步就是找出“谁”在忙。iostat告诉我们设备层面的情况,而iotop和pidstat则能深入到进程级别。
iotop:交互式进程IO监控iotop类似于top命令,但专注于IO。它可以实时显示每个进程的读写速率和累积IO量。
sudo iotop运行后,你会看到一个动态刷新的界面。关键列包括:
TID/PID: 线程/进程ID。PRIO: IO优先级。USER: 进程所有者。DISK READ,DISK WRITE: 实时读写速率。SWAPIN,IO>:IO>列表示进程等待IO的时间百分比,是判断进程是否被IO阻塞的直观指标。
你可以按o键只显示正在产生IO的进程,按p键显示线程信息,按a键显示累积IO量。这对于快速定位某个时间点疯狂读写磁盘的“元凶”非常有效。
pidstat:更详细的进程IO统计pidstat是sysstat包的另一利器,它能提供更结构化、更详细的进程级IO报告,并且方便记录和后期分析。
# 查看所有进程的IO统计,每秒刷新一次,共5次 pidstat -d 1 5输出中,kB_rd/s和kB_wr/s分别表示进程每秒读、写的千字节数,kB_ccwr/s表示因任务取消而写入磁盘的数据量。结合-p参数可以监控特定进程,结合-t参数可以查看线程信息。
注意事项:
iotop需要内核支持(通常已启用),且需要root权限。在某些最小化安装的系统或容器内可能无法使用。pidstat则更为通用和脚本友好。
2.3 系统级综合视图:vmstat与sar
有时候,我们需要在一个更宏观的视角下看IO,理解IO与系统其他资源(如CPU、内存、上下文切换)的关联。
vmstat:系统资源概览vmstat命令提供关于进程、内存、分页、块IO、陷阱和CPU活动的信息。
vmstat 1关注bi(每秒从块设备接收的块数)和bo(每秒发送到块设备的块数,块大小通常为1KB)。这两个值给出了系统级别的块IO吞吐量概览。如果它们持续很高,结合wa(CPU等待IO的时间百分比)也很高,那就明确指示系统存在IO瓶颈。wa值如果长期大于5%,就需要警惕了。
sar:历史数据回溯iostat和vmstat看实时,那历史性能数据怎么看?这就要用到sar(System Activity Reporter),它同样是sysstat包的一部分。sar守护进程会定期收集系统性能数据,默认保存一段时间(通常是一个月)。
# 查看当天磁盘设备的统计信息 sar -d # 查看指定日期的数据(如查看昨天下午2点到3点的数据) sar -d -f /var/log/sa/saXX -s 14:00:00 -e 15:00:00 # XX是日期 # 查看CPU的IO等待时间历史 sar -usar -d的输出字段与iostat -dx类似,但它是历史数据,非常适合用于事后分析性能问题,比如排查“昨天下午3点系统为什么慢”。
2.4 进阶性能剖析:blktrace与fio
当你通过基础工具定位到大概的IO问题后,可能需要更底层的工具进行深度剖析,或者需要主动测试磁盘的极限性能。
blktrace:块层IO追踪blktrace是一个强大的工具,它可以追踪一个IO请求从块设备层(Block Layer)下发到最终完成的全生命周期,生成非常详细的跟踪日志。配合blkparse和btt工具,可以分析出IO在每一个阶段(如Q2C:进入队列到被驱动处理,C2I:驱动处理到硬件中断)所花费的时间,是诊断复杂IO延迟问题的“手术刀”。
# 对设备sda进行追踪,持续10秒 sudo blktrace -d /dev/sda -w 10 # 解析生成的跟踪文件 blkparse -i sda -d sda.bin # 使用btt进行聚合分析 btt -i sda.bin这个工具相对复杂,输出信息量大,通常用于内核开发者或存储工程师进行极端情况下的问题诊断。
fio:灵活的IO压力测试fio(Flexible I/O Tester)不是监控工具,而是性能测试工具。当你想知道你的磁盘(或文件系统)在特定负载模式(如随机读、顺序写、混合读写)下的极限性能(IOPS、带宽、延迟)时,fio是标准选择。你可以用它来基准测试新硬盘,或者模拟生产环境的IO模型来验证系统能力。
# 一个简单的随机读测试示例 fio --name=randread --ioengine=libaio --iodepth=32 --rw=randread --bs=4k --direct=1 --size=1G --numjobs=4 --runtime=60 --time_based --group_reporting这个命令会启动4个线程,每个线程进行4KB随机读,队列深度32,持续60秒,并使用直接IO(绕过缓存)。测试结束后,fio会给出详细的IOPS、带宽和延迟分布报告(如延迟的百分比,clat)。
实操心得:
fio的参数组合千变万化,务必根据你的测试目标来设计。--direct=1和--iodepth是关键参数,前者避免操作系统缓存影响,真实测磁盘性能;后者模拟并发压力。测试前,最好在目标磁盘上创建一个独立的测试文件,避免影响生产数据。
3. 实战场景分析与排查思路
掌握了工具,我们来看几个典型的实战场景,如何串联使用这些工具进行问题排查。
3.1 场景一:应用响应变慢,疑似IO瓶颈
现象:Web应用接口响应时间从平均50ms飙升到2s以上。登录服务器查看,CPU使用率不高(~30%),内存充足,但感觉系统“很卡”。
排查步骤:
- 快速定位:首先运行
iostat -dx 2。发现sdb磁盘的%util持续在95%以上,w_await高达150ms,wkB/s也很高。初步判断是sdb的写入压力极大导致高延迟。 - 找出元凶:保持
iostat运行,另开一个终端运行sudo iotop。很快发现一个名为data_backup.sh的脚本进程及其mysqldump子进程的DISK WRITE列数值极高,IO>列也接近100%。确认是备份任务在全量导出数据库,大量写盘。 - 评估影响:运行
vmstat 1,观察到wa(CPU IO等待)值在40%左右波动,bo(块写出)值很大。这解释了为什么CPU不忙但系统卡——CPU都在等IO完成。 - 制定策略:与业务方确认,该备份任务可以调整。临时方案:通过
ionice或cgroup限制备份进程的IO优先级。长期方案:将备份任务调度到业务低峰期,或使用具有从库进行备份,避免影响主库性能。
3.2 场景二:数据库查询性能周期性下降
现象:MySQL数据库在每天固定时间(如凌晨)查询变慢,但该时段并无业务高峰。
排查步骤:
- 历史数据分析:由于问题是周期性的,首先使用历史数据工具。运行
sar -d -f /var/log/sa/saXX(XX为问题发生日期),查看对应时间段的磁盘统计数据。发现sda磁盘的rkB/s和r/s在问题时段有规律性尖峰,%util和r_await也随之飙升。 - 关联进程分析:检查该时间点的计划任务(
crontab -l)和系统日志(grep相关时间点的/var/log/messages或journalctl)。发现有一个定时的日志分析任务启动,该任务需要顺序扫描大量日志文件。 - 根源分析:日志分析任务是顺序读,本应很快。但进一步用
iostat -dx观察发现,rareq-sz(读请求平均大小)很小,只有几KB。这说明虽然是顺序读文件,但应用程序(可能是某个脚本或工具)是以非常小的块(如fread小缓冲区)进行读取的,导致物理上虽然是顺序访问,但在块设备层却产生了大量的IO请求(高IOPS),拖慢了同时进行的数据库随机读请求(因为磁头要频繁在日志文件和数据库文件间移动)。 - 解决方案:优化日志分析任务的读取逻辑,使用更大的缓冲区(例如从4K调整为64K或128K),减少IOPS。或者,将日志文件放在与数据库不同的物理磁盘上,实现IO隔离。
3.3 场景三:评估SSD替换机械盘的效果
现象:计划将数据库服务器的存储从SATA机械硬盘升级为NVMe SSD,需要量化评估性能提升。
排查步骤:
- 基准测试设计:使用
fio设计测试用例,模拟数据库的典型负载。通常包括:- 随机读:模拟索引查找。
--rw=randread --bs=4k --iodepth=32 - 随机写:模拟更新/插入。
--rw=randwrite --bs=4k --iodepth=32 - 顺序读/写:模拟全表扫描或备份。
--rw=read/write --bs=128k --iodepth=8 - 混合读写:模拟真实负载。
--rw=randrw --rwmixread=70 --bs=4k --iodepth=32
- 随机读:模拟索引查找。
- 执行测试:分别在旧机械盘和新SSD上,使用相同的
fio配置文件运行测试。关键点:确保测试文件足够大(远大于系统缓存),并使用--direct=1绕过页面缓存,测试真实磁盘性能。使用--group_reporting查看聚合报告。 - 指标对比:重点关注以下指标:
- IOPS:随机读写测试结果。机械盘可能只有几百,而NVMe SSD可达数十万甚至百万。
- 带宽:顺序读写测试结果。机械盘约100-200 MB/s,NVMe SSD可达数GB/s。
- 延迟:
clat(完成延迟)的百分比,特别是clat percentiles中的99.00%或99.90%值。机械盘的尾延迟(高百分位延迟)可能高达几十毫秒,而SSD可以稳定在几百微秒到几毫秒。延迟的稳定性和降低对数据库事务性能提升至关重要。
- 生成报告:将两次测试的
fio输出结果保存,并提取关键指标做成表格对比,为决策提供直观数据支持。
4. 常见问题与排查技巧实录
在实际操作中,总会遇到一些令人困惑的输出或现象。这里记录一些常见问题和排查技巧。
4.1 为什么iostat显示的%util会超过100%?
这在多块磁盘的RAID阵列(如RAID 0, RAID 10)上很常见。因为%util是设备繁忙时间的百分比。对于RAID控制器管理的虚拟设备(如/dev/md0),一个逻辑IO可能会并行下发到多块物理磁盘。当这些物理磁盘同时工作时,逻辑设备在统计周期内的“繁忙时间”可能会超过100%。例如,一个双盘RAID 0,如果两块盘都100%繁忙,md0的%util就会显示200%。所以,对于RAID设备,%util失去了其绝对值意义,更应该关注r_await/w_await和吞吐量指标。
4.2iotop显示的总IO速率和iostat对不上?
这通常是正常的,原因有几个:
- 缓存(Cache):
iostat报告的是块设备层的物理IO。而iotop默认报告的是进程发起的、经过VFS(虚拟文件系统)层的IO。如果进程读取的数据在页面缓存(Page Cache)中命中,就不会产生物理磁盘读,iostat看不到,但iotop的进程DISK READ可能会计数(取决于内核版本和设置)。可以使用iotop -P或-a参数查看累积的物理IO,或者使用pidstat -d,它报告的更接近物理IO。 - 合并(Merge):
iostat的rkB/s是合并后写入物理设备的数据量。而进程层发起的多个小IO可能在块层被合并成一个大的物理IO。 - 设备映射:如果使用了LVM、设备映射器(dm)或加密层,
iotop可能看到的是上层逻辑设备的IO,而iostat看到的是底层物理设备或映射设备的IO。
4.3 如何监控容器(Docker/K8s)内的磁盘IO?
容器内的进程看到的往往是宿主机的一部分设备或虚拟设备。直接在主机的iotop里可能无法准确区分容器的IO。有以下几种方法:
- cgroup统计信息:容器的IO限制和统计通过cgroup实现。可以查看对应容器的cgroup目录。
这些文件记录了该cgroup内进程读写的字节数和IO次数。# 找到容器的cgroup ID(如从`docker inspect`获取) # 查看该容器的IO统计(假设使用cgroup v1) cat /sys/fs/cgroup/blkio/docker/<container-id>/blkio.throttle.io_service_bytes cat /sys/fs/cgroup/blkio/docker/<container-id>/blkio.throttle.io_serviced - 使用容器化工具:在宿主机上使用
docker stats命令可以查看容器的实时CPU、内存、网络和块IO使用情况。在Kubernetes中,可以使用kubectl top pod结合Metrics Server,或者通过cAdvisor、Prometheus等监控方案来收集容器级别的IO指标。 - 进入容器内部:
docker exec进入容器,在容器内部使用iostat、iotop等工具。但需要注意,容器内可能没有安装这些工具,且看到的是容器视角的设备(可能是/dev/xvda1等虚拟设备),其统计可能与宿主机视角不同。
4.4 遇到“IO Wait”高,但磁盘工具显示并不忙?
vmstat的wa高,但iostat显示所有磁盘的%util和r_await/w_await都很低。这种情况可能的原因有:
- NFS等网络文件系统:IO等待发生在网络,而不是本地磁盘。需要检查网络延迟和带宽,以及NFS服务器的性能。可以使用
sar -n DEV查看网络流量,或使用nfsiostat(如果可用)专门查看NFS统计。 - 内存压力导致Swap:当物理内存不足时,系统会频繁地将内存页换出(Swap Out)到交换分区(Swap)。这个换出操作是磁盘写,但可能非常零散和随机,导致高IO等待。检查
vmstat的si(swap in)和so(swap out)列,以及free命令查看swap使用情况。 - 文件系统日志(Journaling):如ext4的journal日志写入。这部分写入有时是同步的,可能导致短暂的等待。可以尝试调整文件系统挂载选项(如
data=writeback),但需权衡数据安全风险。 - 锁竞争:有时高
wa并非物理IO慢,而是进程在等待某个文件锁或inode锁。这需要结合pidstat -w(查看上下文切换)和strace、perf等工具分析进程状态。
4.5 排查工具箱速查表
| 问题场景 | 首要检查命令 | 辅助/深入命令 | 关键观察指标 |
|---|---|---|---|
| 系统整体卡顿 | vmstat 1 | iostat -dx 2 | wa> 5%,%util高,r_await/w_await高 |
| 定位高IO进程 | sudo iotop | pidstat -d 1 | DISK READ/WRITE,IO>,kB_rd/s,kB_wr/s |
| 历史性能分析 | sar -d | sar -u,sar -b | 历史时间段的tps,rkB/s,wkB/s,%util |
| 评估磁盘性能 | fio(定制测试) | hdparm -Tt /dev/sda(缓存/缓冲读测试) | IOPS, Bandwidth, Latency (clat percentiles) |
| 容器IO问题 | docker stats | 查看cgroup文件 (/sys/fs/cgroup/...) | 容器级别的读写字节数/次数 |
| 深度延迟分析 | iostat -dx(看await) | blktrace+blkparse+btt | IO请求在各阶段(Q2C, D2C等)的耗时分布 |
| 怀疑Swap导致IO | free -h,vmstat 1 | sar -W 1(查看swap统计) | si,so持续不为0, swap使用率增长 |
掌握这些工具和思路,你就能像一位经验丰富的系统侦探一样,从容应对各种磁盘IO相关的性能谜题。记住,监控的目的不是为了看一堆数字,而是为了建立系统的性能基线,在异常出现时能快速定位、分析和解决。