在讲解磁盘IO前,先简单说下什么是磁盘。磁盘是可以持久化存储的设备,根据存储介质的不同,常见磁盘可以分为两类:机械磁盘和固态磁盘。
第一类,机械磁盘,也称为硬盘驱动器(Hard Disk Driver),通常缩写为 HDD。机械磁盘主要由盘片和读写磁头组成,数据就存储在盘片的环状磁道中。在读写数据前,需要移动读写磁头,定位到数据所在的磁道,然后才能访问数据。显然,如果 I/O 请求刚好连续,那就不需要磁道寻址,自然可以获得最佳性能。这其实就是我们熟悉的,连续 I/O 的工作原理。与之相对应的,当然就是随机 I/O,它需要不停地移动磁头,来定位数据位置,所以读写速度就会比较慢。
第二类,固态磁盘(Solid State Disk),通常缩写为 SSD,由固态电子元器件组成。固态磁盘不需要磁道寻址,所以,不管是连续 I/O,还是随机 I/O 的性能,都比机械磁盘要好得多。
其实,无论机械磁盘,还是固态磁盘,相同磁盘的随机 I/O 都要比连续 I/O 慢很多,原因也很明显。
对机械磁盘来说,刚刚提到过的,由于随机 I/O 需要更多的磁头寻道和盘片旋转,它的性能自然要比连续 I/O 慢。
而对固态磁盘来说,虽然它的随机性能比机械硬盘好很多,但同样存在“先擦除再写入”的限制。随机读写会导致大量的垃圾回收,所以相对应的,随机 I/O 的性能比起连续 I/O 来,也还是差了很多。
此外,连续 I/O 还可以通过预读的方式,来减少 I/O 请求的次数,这也是其性能优异的一个原因。很多性能优化的方案,也都会从这个角度出发,来优化 I/O 性能。
此外,机械磁盘和固态磁盘还分别有一个最小的读写单位。
机械磁盘的最小读写单位是扇区,一般大小为 512 字节。
而固态磁盘的最小读写单位是页,通常大小是 4KB、8KB 等。
如果每次都读写 512 字节这么小的单位的话,效率很低。所以,Linux文件系统会把连续的扇区或页,组成逻辑块,然后以逻辑块作为最小单元来管理数据。常见的逻辑块的大小是 4KB,也就是说,连续 8 个扇区,或者单独的一个页,都可以组成一个逻辑块。
除了可以按照存储介质来分类,另一个常见的分类方法,是按照接口来分类,比如可以把硬盘分为 IDE(Integrated Drive Electronics)、SCSI(Small Computer System Interface) 、SAS(Serial Attached SCSI) 、SATA(Serial ATA) 、FC(Fibre Channel) 等。
不同的接口,往往分配不同的设备名称。比如, IDE 设备会分配一个 hd 前缀的设备名,SCSI 和 SATA 设备会分配一个 sd 前缀的设备名。如果是多块同类型的磁盘,就会按照 a、b、c 等的字母顺序来编号。
除了磁盘本身的分类外,当你把磁盘接入服务器后,按照不同的使用方式,又可以把它们划分为多种不同的架构。
最简单的,就是直接作为独立磁盘设备来使用。这些磁盘,往往还会根据需要,划分为不同的逻辑分区,每个分区再用数字编号。比如我们前面多次用到的 /dev/sda ,还可以分成两个分区 /dev/sda1 和 /dev/sda2。
另一个比较常用的架构,是把多块磁盘组合成一个逻辑磁盘,构成冗余独立磁盘阵列,也就是 RAID(Redundant Array of Independent Disks),从而可以提高数据访问的性能,并且增强数据存储的可靠性。
根据容量、性能和可靠性需求的不同,RAID 一般可以划分为多个级别,如 RAID0、RAID1、RAID5、RAID10 等。
RAID0 有最优的读写性能,但不提供数据冗余的功能。
而其他级别的 RAID,在提供数据冗余的基础上,对读写性能也有一定程度的优化。
最后一种架构,是把这些磁盘组合成一个网络存储集群,再通过 NFS、SMB、iSCSI 等网络存储协议,暴露给服务器使用。(云服务器基本都是这种架构)
其实在 Linux 中,磁盘实际上是作为一个块设备来管理的,也就是以块为单位读写数据,并且支持随机读写。每个块设备都会被赋予两个设备号,分别是主、次设备号。主设备号用在驱动程序中,用来区分设备类型;而次设备号则是用来给多个同类设备编号。
磁盘 I/O(Input/Output)是指计算机系统中涉及到磁盘的数据读取和写入操作。磁盘 I/O 是计算机与存储设备之间进行数据交换的一种重要方式。当计算机需要从磁盘读取数据时,它会发起一个读取请求,磁盘会寻找并将数据传输到计算机的内存中;当计算机需要将数据写入磁盘时,它会发起一个写入请求,将数据从内存写入到磁盘中。
我们都知道磁盘中存储的程序,必须要加载到内存后才能运行,在磁盘中保存的原始程序是无法直接运行的。这是因为,负责解析和运行程序内容的CPU,需要通过内部程序计数器来指定内存地址,然后才能读出程序。即使CPU可以直接读出并运行磁盘中保存的程序,由于磁盘读取速度慢,程序的运行速度还是会降低。总之,存储在磁盘中的程序需要读入到内存后才能运行。
当程序在内存中执行时,如果需要加载一些文档数据或其他文件,它会通过操作系统提供的文件操作功能来实现。操作系统会提供一些函数或系统调用,允许程序访问磁盘上的文件并将其加载到内存中。程序可以使用文件路径指定要加载的文件,然后通过操作系统提供的函数来打开这些文件。一旦文件被打开,程序就可以读取其中的数据,并将其加载到内存中,以便后续处理。这就好像你在读一本书,首先需要打开书本,然后才能阅读其中的内容。 当程序执行 I/O 操作时,CPU 将会暂时停止执行程序指令,而是会等待操作系统完成读取文件的工作。
一旦CPU下发了读取文件的指令,它会等待操作系统通知文件已经准备好,并将数据加载到内存中。CPU会继续执行其他的指令,而不是空闲等待。一旦文件数据加载到内存中,CPU 就会继续执行程序的后续逻辑。在这个过程中,CPU 可能会执行其他指令,例如处理内存中的其他数据,执行其他线程的操作,或者执行程序的其他部分逻辑。 CPU 不会在等待期间完全停止执行。
注意 1:当CPU需要等待磁盘操作完成才能继续处理数据时,它可能会进入空闲状态,这时,CPU的使用率下降,因为它正在等待IO操作,而不是执行计算任务,这种现象说明了IO操作对CPU性能的重要影响。
注意 2:内存相当于CPU和硬盘之间的桥梁,当需要运行一个程序时,先将程序加载到内存中,然后CPU取内存中的指令和数据进行处理运算,处理完后将结果写回内存,如果需要的话再将结果从内存写入硬盘。
说到磁盘性能的衡量标准,必须要提到五个常见指标,也就是我们经常用到的,使用率、饱和度、IOPS、吞吐量以及响应时间等。这五个指标,是衡量磁盘性能的基本指标:
了解磁盘的性能指标,只是我们 I/O 性能测试的第一步。接下来,又该用什么方法来观测它们呢?这里,介绍几个常用的 I/O 性能观测方法。
iostat是I/O statistics(输入/输出统计)的缩写,iostat工具将对系统的磁盘操作活动进行监视。它的特点是汇报磁盘活动统计情况,同时也会汇报出CPU使用情况。iostat也有一个弱点,就是它不能对某个进程进行深入分析,仅对系统的整体情况进行分析。
- # iostat属于sysstat软件包。可以直接安装。
- yum install sysstat -y
选项说明:
- -c: 仅显示CPU利用率相关信息;
- -d: 仅显示磁盘I/O相关信息;
- -k: 显示输出的数据单位为KB/s而不是默认的字节/s;
- -t: 在输出中显示时间戳(时间戳格式YYYY-MM-DD HH:MM:SS)。
- -m:显示状态以兆字节每秒为单位;
- -p:仅显示块设备和所有被使用的其他分区的状态;
- -V:显示版号并退出;
- -x:显示扩展状态。
iostat 的详细使用本文不再赘余,详情见《Linux命令拾遗-%iowait指标代表了什么? 》这篇文章。
在iostat输出的这些指标中,需要注意:
在观测指标时,也别忘了结合请求的大小( rareq-sz 和 wareq-sz)一起分析。你可能注意到,从 iostat 并不能直接得到磁盘饱和度。事实上,饱和度通常也没有其他简单的观测方法,不过,你可以把观测到的平均请求队列长度或者读写请求完成的等待时间,跟基准测试的结果(比如通过 fio)进行对比,综合评估磁盘的饱和情况。
除了每块磁盘的 I/O 情况,每个进程的 I/O 情况也是我们需要关注的重点。上面提到的 iostat 只提供磁盘整体的 I/O 性能数据,缺点在于,并不能知道具体是哪些进程在进行磁盘读写。要观察进程的 I/O 情况,还可以使用iotop这个工具。iotop。它是一个类似于 top 的工具,你可以按照 I/O 大小对进程排序,然后找到 I/O 较大的那些进程。
- #安装
- yum -y install iotop
选项说明:
- • --version #显示版本号
- • -h, --help #显示帮助信息
- • -o, --only #显示进程或者线程实际上正在做的I/O,而不是全部的,可以随时切换按o
- • -b, --batch #运行在非交互式的模式
- • -n NUM, --iter=NUM #在非交互式模式下,设置显示的次数,
- • -d SEC, --delay=SEC #设置显示的间隔秒数,支持非整数值
- • -p PID, --pid=PID #只显示指定PID的信息
- • -u USER, --user=USER #显示指定的用户的进程的信息
- • -P, --processes #只显示进程,一般为显示所有的线程
- • -a, --accumulated #显示从iotop启动后每个线程完成了的IO总数
- • -k, --kilobytes #以千字节显示
- • -t, --time #在每一行前添加一个当前的时间
- • -q, --quiet #suppress some lines of header (implies --batch). This option can be specified up to three times to remove header lines.
- • -q column names are only printed on the first iteration,
- • -qq column names are never printed,
- • -qqq the I/O summary is never printed.
-
- iotop 快捷键
- • 左右箭头 #改变排序方式,默认是按IO排序
- • r #改变排序顺序
- • o #只显示有IO输出的进程
- • p #进程/线程的显示方式的切换
- • a #显示累积使用量
- • q #退出
iotop 的输出如下所示:
- $ iotop
- Total DISK READ : 0.00 B/s | Total DISK WRITE : 7.85 K/s
- Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 0.00 B/s
- TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
- 15055 be/3 root 0.00 B/s 7.85 K/s 0.00 % 0.00 % systemd-journald
从这个输出,可以看到,前两行分别表示,进程的磁盘读写大小总数和磁盘真实的读写大小总数。因为缓存、缓冲区、I/O 合并等因素的影响,它们可能并不相等。剩下的部分,则是从各个角度来分别表示进程的 I/O 情况,包括线程 ID、I/O 优先级、每秒读磁盘的大小、每秒写磁盘的大小、换入和每个进程的 I/O 利用率(即进程正在进行的 I/O 操作所占用的时间比例)。
ostat 和 iotop 命令都主要用于实时监控系统的 I/O 情况,通常不会记录历史的 I/O 信息。如果你需要查看历史的 I/O 信息,可以考虑使用sar命令。
sar 命令是分析系统瓶颈的神器,可以用来查看 CPU 、内存、磁盘、网络等性能,sar 命令查看当前磁盘性能的命令为:
- [root@106 sa]# sar -d -p 1 2
- Linux 3.10.0-1160.59.1.el7.x86_64 (106) 2024年04月18日 _x86_64_ (8 CPU)
-
- 17时33分33秒 DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util
- 17时33分34秒 sdc 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- 17时33分34秒 sdd 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- 17时33分34秒 sdb 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- 17时33分34秒 sda 25.00 0.00 276.00 11.04 0.00 0.16 0.16 0.40
- 17时33分34秒 centos-root 25.00 0.00 276.00 11.04 0.00 0.16 0.16 0.40
- 17时33分34秒 centos-swap 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
-
- 17时33分34秒 DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util
- 17时33分35秒 sdc 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- 17时33分35秒 sdd 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- 17时33分35秒 sdb 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- 17时33分35秒 sda 153.00 0.00 1444.00 9.44 0.85 5.55 0.29 4.40
- 17时33分35秒 centos-root 153.00 0.00 1444.00 9.44 0.85 5.54 0.29 4.40
- 17时33分35秒 centos-swap 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
-
- 平均时间: DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util
- 平均时间: sdc 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- 平均时间: sdd 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- 平均时间: sdb 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- 平均时间: sda 89.00 0.00 860.00 9.66 0.43 4.79 0.27 2.40
- 平均时间: centos-root 89.00 0.00 860.00 9.66 0.43 4.79 0.27 2.40
- 平均时间: centos-swap 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- [root@106 sa]#
其中, “-d”参数代表查看磁盘性能,“-p”参数代表将 dev 设备按照 sda,sdb……名称显示,“1”代表每隔1s采取一次数值,“2”代表总共采取2次数值。输出项除了tps,其他指标和iostat一致,这里就不再赘余(tps:每秒钟物理设备的 I/O 传输总量)。
默认情况下,sar显示当前数据;如果想继续查看一天前的报告;可以查看保存在/var/log/sa/下的sar日志(默认保存三天数据):
- [root@106 sa]# sar -d -p -f /var/log/sa/sa16
- Linux 3.10.0-1160.59.1.el7.x86_64 (106) 2024年04月16日 _x86_64_ (8 CPU)
-
- 14时10分01秒 DEV tps rd_sec/s wr_sec/s avgrq-sz avgqu-sz await svctm %util
- 14时20分01秒 sdc 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- 14时20分01秒 sdd 0.04 0.00 0.36 9.00 0.00 2.12 2.12 0.01
- 14时20分01秒 sdb 0.01 0.00 0.12 9.00 0.00 0.38 0.38 0.00
- 14时20分01秒 sda 49.17 0.00 888.31 18.07 0.07 1.41 0.58 2.85
- 14时20分01秒 centos-root 49.42 0.00 888.30 17.97 0.07 1.43 0.58 2.85
- ......
- 23时40分01秒 sdc 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- 23时40分01秒 sdd 0.04 0.00 0.36 9.00 0.00 0.79 0.79 0.00
- 23时40分01秒 sdb 0.01 0.00 0.12 9.00 0.00 1.62 1.62 0.00
- 23时40分01秒 sda 48.50 0.00 892.42 18.40 0.08 1.57 0.63 3.07
- 23时40分01秒 centos-root 48.71 0.00 892.42 18.32 0.08 1.58 0.63 3.07
- 23时40分01秒 centos-swap 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- 23时50分01秒 sdc 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- 23时50分01秒 sdd 0.04 0.00 0.36 9.00 0.00 0.25 0.25 0.00
- 23时50分01秒 sdb 0.01 0.00 0.12 9.00 0.00 0.25 0.25 0.00
- 23时50分01秒 sda 49.29 0.00 824.63 16.73 0.07 1.52 0.64 3.18
- 23时50分01秒 centos-root 49.50 0.00 824.63 16.66 0.08 1.53 0.64 3.18
- 23时50分01秒 centos-swap 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
- 平均时间: sdc 0.00 0.47 0.01 208.69 0.00 4.06 2.78 0.00
- 平均时间: sdd 0.04 0.00 0.37 9.08 0.00 0.49 0.48 0.00
- 平均时间: sdb 0.02 0.00 0.14 9.31 0.00 0.53 0.50 0.00
- 平均时间: sda 48.53 0.00 863.51 17.79 0.07 1.46 0.61 2.97
- 平均时间: centos-root 48.74 0.00 863.51 17.71 0.07 1.47 0.61 2.97
- 平均时间: centos-swap 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
(2)其他IO相关的常用命令
本文梳理了磁盘、 Linux IO、IO性能指标和性能工具。我们通常用 IOPS、吞吐量、使用率、饱和度以及响应时间等几个指标,来评估磁盘的 I/O 性能。可以用 iostat 获得磁盘的 I/O 情况,也可以用iotop 观察进程的 I/O 情况。不过在分析这些性能指标时,要注意结合读写比例、I/O 类型以及 I/O 大小等,进行综合分析。