存储子系统
存储子系统常见的IO异常问题包含文件系统问题、IO性能问题和存储硬件问题。文件系统和存储硬件问题通常可以在内核日志中看到相关的报错,通过收集内核日志和硬件日志分析定位。IO性能问题性能常常会导致业务性能不佳,并与应用软件、中间件基础软件、硬件等强相关,可能是在操作系统到硬件RAID卡、硬盘出现了一些配合问题,需针对IO路径上各模块进行分析定位。
磁盘存储子系统路径
下图通过一次磁盘 write 操作的过程(假设文件已经被从磁盘中读入了 page cache中)来概述存储子系统的工作原理。
- 用户进程通过 write() 系统调用发起写请求。
- 内核更新对应的 page cache。
- pdflush 内核线程将 page cache 写入至磁盘中。
- 文件系统层将每一个 block buffer 存放为一个 bio 结构体,并向块设备层提交一个写请求。
- 块设备层从上层接受到请求,执行 IO 调度操作,并将请求放入IO 请求队列中。
- 设备驱动(如 SCSI 或RAID卡驱动)完成写操作。
- 磁盘设备固件执行对应的硬件操作,如磁盘的旋转,寻道等,数据被写入到磁盘扇区中。

访问模型分析
了解I/O的特点对于优化系统性能非常重要,I/O是顺序的还是随机的,是读操作还是写操作,读写的比例是多少,I/O数据块的大小,这些都是影响性能的关键因素。iostat是一个可以查看块设备运行状态的工具,通过iostat工具可以对IO模型和性能进行初步的分析。

如上图所示,iostat主要参数主要指标含义如下:
- rareq-sz/wareq-sz
表示读/写平均请求块大小,单位为sector(512B)。
- MB/s wMB/s
当前读写带宽
- rrqm/s wrqm/s
如wrqm/s 远远大于 w/s,说明顺序IO较多,有大量的IO请求被合并,如果wrqm/s 和w/s数量基本相当,那么说明IO基本上没有多少合并,随机读写多。
- aqu-sz
表示当前队列里面平均IO请求个数。该值越大,表示存储硬件无法快速处理过多的IO请求,需要审视当前配置是否满足业务要求。
- %util
表示向设备发出 I/O 请求的运行时间百分比(设备的带宽利用率),换句话说就是一秒中有百分之多少的时间用于 I/O 操作。当连续处理请求的设备的这个值接近100%时,说明产生的 I/O 请求太多,I/O 系统已经满负荷,该磁盘可能存在瓶颈。但是对于并行处理请求的设备,例如 RAID 阵列和现代 SSD,这个数字并不反映它们的性能限制,即无法衡量磁盘设备的饱和度。
根据上述指标可以计算IO的读写比例,读写数据大小等信息,计算方法如下表。
| 其他指标 | 说明 |
|---|---|
| 读写比例 | r/s : w/s |
| 读顺序随机比 | rrqm/s : r/s rrqm/s为0说明为随机读IO |
| 写顺序随机比 | wrqm/s : w/s wrqm/s为0说明为随机写IO |
| 读数据块大小 | rMB/s * 1024 ÷ r/s |
| 写数据块大小 | wMB/s * 1024 ÷ w/s |
| 同步/异步 | Avgqu-sz > 1说明存在异步IO |
IO 来源监控
iotop是一个用来监视磁盘I/O使用状况的top类工具,可监测到哪一个进程使用的磁盘IO的信息。Linux下的IO统计工具如iostat等大多数是只能统计到每个设备的读写情况,如果想知道每个进程是如何使用IO就需要使用iotop工具。通过输出结果,可以清楚地观测是哪些程序在读写磁盘,读写速度以及运行的命令行,pid 等信息。
IO 子系统耗时统计
blktrace是一个用户态的工具,提供 I/O 子系统上时间如何消耗的详细信息, 从中可以分析是IO调度慢还是硬件响应慢等;配套工具 blkparse 从 blktrace 读取原始输出,并产生可读的输入和输出操作摘要;btt 作为 blktrace 软件包的一部分而被提供,它分析 blktrace 输出,并显示该数据用在每个 I/O 栈区域的时间量,能够更容易的在 I/O 子系统中发现瓶。

- Q2Q:多个发送到块IO层请求的时间间隔;
- Q2G:生成IO请求所消耗的时间,包括remap(可能被DM(Device Mapper)或MD(Multiple Device, Software RAID) remap到其它设备)和split(可能会因为I/O请求与扇区边界未对齐、或者size太大而被分拆(split)成多个物理I/O)的时间;
- G2I:IO请求进入IO Scheduler所消耗的时间,包括merge(可能会因为与其它I/O请求的物理位置相邻而合并成一个I/O)的时间;
- I2D:IO请求在IO Scheduler中等待的时间;
- D2C:IO请求在driver和硬件上(IO请求被driver提交给硬件,经过HBA、电缆(光纤、网线等)、交换机(SAN或网络)、最后到达存储设备,设备完成IO请求之后再把结果发回)所消耗的时间;
- Q2C:
整个IO请求所消耗的时间(Q2I + I2D + D2C = Q2C),相当于iostat的await。
案例-swap 分区占用导致进程运行慢
- 问题现象
某项目反馈业务读写文件性能很差,且磁盘IO占用高。
- 原因分析
通过iostat命令查看sdb盘饱和度接近100%,出现性能瓶颈。但sdb是做为系统盘而非数据盘,同业务开发人员沟通业务软件除日志文件在系统盘以外并没有对系统盘做数据读写操作,那么如何确认这些 I/O请求来源。

通过iotop观察到业务进程存在持续的交换内存使用,判断是此处导致了性能问题。

通过执行lsblk可以查看到io使用率高的分区正是swap分区。

即业务进程内存配置过高,当系统没有足够物理内存来应付所有请求的时候就会用到swap 设备,swap 设备可以是一个文件,也可以是一个磁盘分区。使用 swap 的代价比较大,如果系统没有物理内存可用,频繁swapping,且程序正要访问的数据已经交换到swap分区,会碰到严重的 IO 问题,最终导致整个系统迟缓。
- 解决方案
即业务进程内存配置过高,当系统没有足够物理内存来应付所有请求的时候就会用到swap 设备,swap 设备可以是一个文件,也可以是一个磁盘分区。使用 swap 的代价比较大,如果系统没有物理内存可用,频繁swapping,且程序正要访问的数据已经交换到swap分区,会碰到严重的 IO 问题,最终导致整个系统迟缓。
评价此篇文章
