1、什么是磁盘
在讲解磁盘IO前,先简单说下什么是磁盘。磁盘是可以持久化存储的设备,根据存储介质的不同,常见磁盘可以分为两类:机械磁盘和固态磁盘。
1.1 机械磁盘
第一类,机械磁盘,也称为硬盘驱动器(Hard Disk Driver),通常缩写为 HDD。**机械磁盘主要由盘片和读写磁头组成,数据就存储在盘片的环状磁道中。在读写数据前,需要移动读写磁头,定位到数据所在的磁道,然后才能访问数据。**显然,如果 I/O 请求刚好连续,那就不需要磁道寻址,自然可以获得最佳性能。这其实就是我们熟悉的,连续 I/O 的工作原理。与之相对应的,当然就是随机 I/O,它需要不停地移动磁头,来定位数据位置,所以读写速度就会比较慢。
1.2 固态磁盘
第二类,固态磁盘(Solid State Disk),通常缩写为 SSD,由固态电子元器件组成。固态磁盘不需要磁道寻址,所以,不管是连续 I/O,还是随机 I/O 的性能,都比机械磁盘要好得多。
1.3 机械磁盘和固态磁盘对比
其实,无论机械磁盘,还是固态磁盘,相同磁盘的随机 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 个扇区,或者单独的一个页,都可以组成一个逻辑块。
1.4 按照接口进行磁盘分类
除了可以按照存储介质来分类,另一个常见的分类方法,是按照接口来分类,比如可以把硬盘分为 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 等的字母顺序来编号。
1.5 磁盘架构
除了磁盘本身的分类外,当你把磁盘接入服务器后,按照不同的使用方式,又可以把它们划分为多种不同的架构。
最简单的,**就是直接作为独立磁盘设备来使用。**这些磁盘,往往还会根据需要,划分为不同的逻辑分区,每个分区再用数字编号。比如我们前面多次用到的 /dev/sda ,还可以分成两个分区 /dev/sda1 和 /dev/sda2。
另一个比较常用的架构,是把多块磁盘组合成一个逻辑磁盘,构成冗余独立磁盘阵列,也就是 RAID(Redundant Array of Independent Disks),从而可以提高数据访问的性能,并且增强数据存储的可靠性。
根据容量、性能和可靠性需求的不同,RAID 一般可以划分为多个级别,如 RAID0、RAID1、RAID5、RAID10 等。
- RAID0 有最优的读写性能,但不提供数据冗余的功能。
- 而其他级别的 RAID,在提供数据冗余的基础上,对读写性能也有一定程度的优化。
最后一种架构,是把这些磁盘组合成一个网络存储集群,再通过 NFS、SMB、iSCSI 等网络存储协议,暴露给服务器使用。(云服务器基本都是这种架构)
其实在 Linux 中,磁盘实际上是作为一个块设备来管理的,也就是以块为单位读写数据,并且支持随机读写。每个块设备都会被赋予两个设备号,分别是主、次设备号。主设备号用在驱动程序中,用来区分设备类型;而次设备号则是用来给多个同类设备编号。
2、什么是磁盘IO
磁盘 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取内存中的指令和数据进行处理运算,处理完后将结果写回内存,如果需要的话再将结果从内存写入硬盘。
3、磁盘性能指标
说到磁盘性能的衡量标准,必须要提到五个常见指标,也就是我们经常用到的,使用率、饱和度、IOPS、吞吐量以及响应时间等。这五个指标,是衡量磁盘性能的基本指标:
- IOPS(Input/Output Per Second),是指每秒磁盘处理的I/O请求数量。衡量存储性能一般看吞吐量(传输速度)和IOPS两个指标。
- 吞吐量,是指每秒磁盘处理的 I/O 请求大小,吞吐量主要指大文件的连续读写速度,在大文件的复制、备份等场景适用,用"HD Tune专业版"中的"基准"测试功能即可测试出磁盘的吞吐量,一般传统机械sata硬盘的顺序读写速度为 :80~150M/s,SAS硬盘为150~200M/s,SSD固态硬盘为400~600M/s。
- 响应时间,是指 I/O 请求从发出到收到响应的间隔时间。
- 使用率,是指磁盘处理 I/O 的时间百分比。过高的使用率(比如超过 80%),通常意味着磁盘 I/O 存在性能瓶颈,这里要注意的是,使用率只考虑有没有 I/O,而不考虑 I/O 的大小。换句话说,当使用率是 100% 的时候,磁盘依然有可能接受新的 I/O 请求,比如磁盘一直读写小文件,虽然使用率是100%,但是磁盘压力可能并不大。
- 饱和度,是指磁盘处理 I/O 的繁忙程度。过高的饱和度,意味着磁盘存在严重的性能瓶颈。当饱和度为 100% 时,磁盘无法接受新的 I/O 请求。
这些指标,很可能是你经常挂在嘴边的,一讨论磁盘性能必定提起的对象。不过我还是要强调一点,不要孤立地去比较某一指标,而要结合读写比例、I/O 类型(随机还是连续)以及 I/O 的大小,综合来分析。举个例子,在数据库、大量小文件等这类随机读写比较多的场景中,IOPS 更能反映系统的整体性能;而在多媒体等顺序读写较多的场景中,吞吐量才更能反映系统的整体性能。
一般来说,我们在为应用程序的服务器选型时,要先对磁盘的 I/O 性能进行基准测试,以便可以准确评估,磁盘性能是否可以满足应用程序的需求。但还是那句话,因地制宜,灵活选取。在基准测试时,一定要注意根据应用程序 I/O 的特点,来具体评估指标。当然,这就需要你测试出,不同 I/O 大小(一般是 512B 至 1MB 中间的若干值)分别在随机读、顺序读、随机写、顺序写等各种场景下的性能情况。用性能工具得到的这些指标,可以作为后续分析应用程序性能的依据。一旦发生性能问题,你就可以把它们作为磁盘性能的极限值,进而评估磁盘 I/O 的使用情况。
4、磁盘 I/O 观测
了解磁盘的性能指标,只是我们 I/O 性能测试的第一步。接下来,又该用什么方法来观测它们呢?这里,介绍几个常用的 I/O 性能观测方法。
4.1 观察每块磁盘的使用情况
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输出的这些指标中,需要注意:
- %util ,就是我们前面提到的磁盘 I/O 使用率;
- r/s+ w/s ,就是 IOPS;
- rkB/s+wkB/s ,就是吞吐量;
- r_await 或 w_await ,就是响应时间。
在观测指标时,也别忘了结合请求的大小( rareq-sz 和 wareq-sz)一起分析。你可能注意到,从 iostat 并不能直接得到磁盘饱和度。事实上,饱和度通常也没有其他简单的观测方法,不过,你可以把观测到的平均请求队列长度或者读写请求完成的等待时间,跟基准测试的结果(比如通过 fio)进行对比,综合评估磁盘的饱和情况。
4.2 观察进程io的使用情况
除了每块磁盘的 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 的时钟百分比等。
4.3 磁盘性能观测命令补充
(1)sar命令
iostat 和 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 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相关的常用命令
5、小结
本文梳理了磁盘、 Linux IO、IO性能指标和性能工具。我们通常用 IOPS、吞吐量、使用率、饱和度以及响应时间等几个指标,来评估磁盘的 I/O 性能。可以用 iostat 获得磁盘的 I/O 情况,也可以用iotop 观察进程的 I/O 情况。不过在分析这些性能指标时,要注意结合读写比例、I/O 类型以及 I/O 大小等,进行综合分析。
参考:《Linux性能优化实战 基础篇:Linux 磁盘I/O是怎么工作的(上)》
参考:《Linux性能优化实战 基础篇:Linux 磁盘I/O是怎么工作的(下)》
参考:《查看IO进程》