文章目录
- 一、主流磁盘结构
- (一)、不划分逻辑卷的结构
- (二)、划分逻辑卷的结构
- 二、常用命令
- (一)、查看磁盘结构命令一 lsblk
- (二)、查看磁盘结构命令二 pvdisplay
- (三)、查看磁盘已经使用的容量 df -h
- (四)、查看虚拟卷别名对应的块设备名 ll /dev/mapper
- (五)、查看当前系统 I/O 状况 iostat -x
- 三、磁盘性能瓶颈的判断依据
以前做性能测试的时候,磁盘瓶颈总是判断的不太准确,这两天仔细研究了一下,记录一下研究的结果。
一、主流磁盘结构
现在主流的磁盘结构有两种:
(一)、不划分逻辑卷的结构
物理磁盘(sda ssd/hdd)↓ 分区1(sda1)→ 文件系统 → 挂载 /boot ↓ 分区2(sda2)→ 文件系统 → 挂载 / ↓ 分区3(sda3)→ 文件系统 → 挂载 /data比如把 sda 划分了 3 个分区,其中 1 个叫 sda1,格式化成 ext4 或 xfs 格式(文件系统),挂载到了/boot 目录下。
这种结构在磁盘空间不足的时候扩展起来不方便,适合小的系统。具体的原因是要实现存储扩展需要连续的存储空间,但是很难把两块硬盘从物理上前后连起来形成连续的存储空间。
(二)、划分逻辑卷的结构
物理磁盘 sda(SSD/HDD) ↓ 物理分区 sda2 【标记为LVM物理卷 PV】 ↓ 卷组 VG(vg0):把一个或多个PV的空间打包成一个大资源池 ↓ 逻辑卷 LV(vg0‑root、vg0‑swap)↓ 格式化文件系统(xfs/ext4)→ 挂载到 / 、swap一块物理磁盘PV可以进行分区(sda->sda1+sda2),多个分区可以组合成一个卷组(sda2->vg0,组成vg0卷组的只有一个 sda2,真实情况下可能还会有 hd1,hda2 等等),这个卷组就是一个大的资源池,在卷组下可以划分逻辑卷(vg0->vg0-root+vg0-swap),逻辑卷可以格式化后挂载到目标目录下。
这种结构的卷组是可扩展的,因为有了 PV->VG->LV 的三层映射关系,当 LV 的空间满了,如果当前 VG 中还有剩余空间,可以直接申请扩充 PE(VG 系统中把 PV 组合后划分的最小存储单元),如果 VG 没有空间了,还可以给 VG 添加新的 PV,重新切割成 PE,再把 PE 分配给 VG。
二、常用命令
(一)、查看磁盘结构命令一 lsblk
[test@kylinv10 security]$ lsblk NAME MAJ:MIN RM SIZE R0 TYPE MOUNTPOINT sda8:00100G0disk|-sda18:101G0part /boot|-sda28:2099G0part|-vg0-root253:0091.1G0lvm /|-vg0-swap253:107.9G0lvm[swap]NAME磁盘名称,sda第一块物理磁盘;sda1/sda2磁盘分区;vg0‑root/vg0‑swapLVM 逻辑卷MAJ:MIN主 / 次设备号,内核识别硬件的编号RM是否可移动磁盘,0=本地硬盘,1=U盘/移动盘SIZE容量R0是否只读只读标志,0=可读写TYPE设备类型,disk物理磁盘,part普通分区,lvm 逻辑卷MOUNTPOINT挂载点,[swap]代表交换分区
(二)、查看磁盘结构命令二 pvdisplay
这个命令需要 root 权限,一般用的比较少
[test@kylinv10 /]$ pvdisplay --- Physical volume --- PV Name /dev/sdb VG Name vg01 PV SIZE31.43TiB / not usable4.00MiB Allocatable yes(but full)PE Size4.00MiB Total PE8240183Free PE0Allocated PE8240183PV UUID Xoo**-**-** --- Physical volume --- PV Name /dev/sdc VG Name vg01 PV SIZE31.43TiB / not usable4.00MiB Allocatable yes(but full)PE Size4.00MiB Total PE8240183Free PE0Allocated PE8240183PV UUID Xoo**-**-**从上面可以看出来,我的机器上有两块大盘 /dev/sdb、/dev/sdc,都作为 PV 加入同一个卷组 vg01。两块盘大小完全一致:每块 31.43TiB,PE 默认 4MiB,两个 PV 的空间已经全部分配给了vg01,Free PE = 0,vg01 卷组已经没有可再分配给逻辑卷的空闲空间。
(三)、查看磁盘已经使用的容量 df -h
[test@kylinv10 /]$df-h文件系统 容量 已用 可用 已用% 挂载点 devtmpfs3.9G03.9G0% /dev tmpfs3.9G 12K3.9G1% /dev/shm tmpfs3.9G 138M3.8G4% /run tmpfs3.9G03.9G0% /sys/fs/cgroup /dev/mapper/vg0-root 92G9.3G 82G11% / tmpfs3.9g2.6K3.9G1% /tmp /dev/sda1 1014M 529M 486M53% /boot10.128.*.*/test_req 20G1.2G 19G6% /test_req tmpfs 795M0795M0% /run/user/501 tmpfs 795M0795M0% /run/user/0 tmpfs 795M0795M0% /run/user/503文件系统有三类,分别是 devtmpfs,tmpfs 和 带路径的存储盘。
第一类是devtmpfs内存存储,每次重启先清空后创建
- 系统设备目录,存放磁盘、网卡、串口等硬件设备文件
- 全部在内存,不消耗磁盘;容量约等于机器一半物理内存;
0已用代表设备节点几乎不占存储。
第二类是tmpfs内存存储,重启清空
/dev/shm共享内存;程序、Docker、数据库会用这块内存盘做共享内存通信。/run:系统运行时目录,存 PID 文件、socket 套接字、服务临时状态。/sys/fs/cgroupcgroup 相关挂载,内核用来限制进程 CPU、内存资源(docker 底层依赖 cgroup)。/run/user/<uid>:每个登录用户独立的 tmpfs- uid=0 是 root;501、503 是普通业务用户;
- 用户登录时自动创建,用户退出登录自动销毁;内存存储,用于存放该用户的桌面、会话 socket 临时文件。
第三类是带路径的普通存储盘,存用户文件
/dev/sda1硬盘的第 1 个分区,挂载到/boot,存储内核引导文件/dev/mapper/vg0-root第 0 个卷组的 root 卷,主要的存储空间10.128.*.*/test_req我挂载的共享存储 NAS 目录
(四)、查看虚拟卷别名对应的块设备名 ll /dev/mapper
[test@kylinv10 /]$ ll /dev/mapper 总用量0crw-------1root root10,2366月1900:41 control lrwxrwxrwx1root root76月1900:41 vg0-root ->../dm-0 lrwxrwxrwx1root root76月1900:41 vg0-swap ->../dm-1dev/dm‑0(dm‑X):内核真实设备,内核只认识这个编号;/dev/mapper/vg0‑root:人为做的软链接,别名,给人看的,方便识别卷组‑逻辑卷名字
Linux 内核访问块设备,根本不认识vg0‑root这种人类命名。
内核识别设备唯一标识:主设备号:次设备号
device‑mapper 的主设备号固定是253:
253:0→/dev/dm‑0253:1→/dev/dm‑1
内核、驱动、io 调度、磁盘调度策略,全部操作的是dm‑0/dm‑1。
软链接/dev/mapper/vg0‑root只是文件系统层面的符号链接,内核根本不知道这个名字存在。
把这个软链接删掉,系统照样跑,只是人类不方便识别设备。
(五)、查看当前系统 I/O 状况 iostat -x
[test@kylinv10 /]$ iostat Linux4.19.90-89.4.v2401.ky10.x86_64(kylinv10)2026年 08 月14日 (4CPU) avg-cpu: %user %nice %system %iowait %steal %idle0.170.000.150.000.0099.68Divce r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz d/s dkB/s drqm/s %drqm d_await dareq-sz aqu-ze %util dm-00.020.54002.6737.840.4410.1003.0616.0400000000.06dm-10.010.53002.6737.840.4410.1003.0616.0400000000.06sda0.030.53002.6737.840.4410.1003.0616.0400000000.06| 序号 | 列名 | 英文 | 中文 | 备注 |
|---|---|---|---|---|
| 1 | Device | This column gives the device (or partition) name as listed in the /dev directory. | 磁盘或分区名 | |
| 2 | sec/s(kB/s,MB/s) | The number of sectors(kibibytes,mebibytes) read from,written to or discarded for the device per second. | 每秒速度总和,包括读,写和忽略三种操作。单位可以是扇区数(1 个扇区 512 个 字节Byte),KiB 和 MiB | |
| 3 | r/s | The number(after merges) of read requests completed per second for the device | 每秒钟读磁盘的次数。 | after merges 代表系统会把多个相邻的读请求合并成一次读磁盘的操作。 |
| 4 | rsec/s(rkB/s,rMB/s) | The number of sectors(kibibytes,mebibytes) read from the device per second. | 每秒钟读取的数据量大小,单位可以是扇区数,KiB 和 MiB | |
| 5 | rrqm/s | The number of read requests merged per second that were queued to the device | 每秒钟合并的读请求数量 | |
| 6 | %rrqm | The percentage of read requests merged together before being sent to the device . | 合并请求的百分比=被合并的请求数量/总的请求数量。比如 1 秒钟内来了 100 个请求,其中 30 个请求读的是连续的磁盘空间,那么这 30 个请求就会被合并成 1 个,有 29 个请求被合并了。发送给磁盘的请求数就是 70+1=71 个。%rrqm = 29/100 = 29%。 从 iostat 输出的内容看 %rrqm = (rrqm/s)/(rrqm/s)+(r/s) | 这个比例越高,说明磁盘读请求被合并的比例高,效率就比较好,如果是 0 代表读的都是分散的区间,效率就不如读连续的区间高。 |
| 7 | r_await | The average time(in milliseconds) for read requests issued to the device to be served.This includes the time spent by the requests in queue and the time spend servicing them. | 表示设备读请求的平均服务时间(单位为毫秒)。该数值包含了两个部分: + 请求在队列中等待的时间。 + 实际 servicing(处理)请求所花费的时间。 | |
| 8 | rareq-sz | The average size(in kibibytes) of the read requests that were issued to the device. | 读磁盘请求的平均大小,以 KiB 为计量单位 | Windows 中的 1KB 有的时候表示 1000KB,有的时候表示 1024KB,Linux 中 一般 以 1024 作为换算比例1KiB=1024B |
| 9 | w/s | The number(after merges) of write requests completed per second for the device | 每秒钟写磁盘的次数。 | after merges 代表系统会把多个相邻的写请求合并成一次读磁盘的操作。 |
| 10 | wsec/s(wkB/s,wMB/s) | The number of sectors(kibibytes,mebibytes) written to the device per second. | 每秒钟写入磁盘的数据量大小,单位可以是扇区数,KB 和 MB | |
| 11 | wrqm/s | The number of write requests merged per second that were queued to the device | 每秒钟合并的写请求数量 | |
| 12 | %wrqm | The percentage of write requests merged together before being sent to the device. | 合并请求的百分比=被合并的请求数量/总的请求数量。比如 1 秒钟内来了 100 个请求,其中 30 个请求读的是连续的磁盘空间,那么这 30 个请求就会被合并成 1 个,有 29 个请求被合并了。发送给磁盘的请求数就是 70+1=71 个。%rrqm = 29/100 = 29%。 | 这个比例越高,说明磁盘写请求被合并的比例高,效率就比较好,如果是 0 代表写的都是分散的区间,效率就不如读连续的区间高。 |
| 13 | w_await | The average time(in millseconds) for write requests issued to the devie to be served.This includes the time spent by the requests in queue and the time spent servcing them. | 表示设备写请求的平均服务时间(单位为毫秒)。该数值包含了两个部分: + 请求在队列中等待的时间。 + 实际 servicing(处理)请求所花费的时间。 | |
| 14 | wareq-sz | The average size(in kibibytes) of the write requests that issued to the device. | 读磁盘请求的平均大小,以 KiB 为计量单位 | |
| 15 | d/s | The number(after merges) of discard requests completed per second for the device | 每秒钟合并的 discard 请求数。 | discard 操作用于通知SSD哪些块已不再被文件系统使用,帮助SSD控制器提前完成垃圾回收,避免后续写入时才执行擦除操作,减少写放大,提升长期读写性能,同时延长闪存颗粒的使用寿命。 |
| 16 | dsec/s(dkB/s,dMB/s) | The number of sectors(kibibytes,mebibytes) discarded for the device per second. | 每秒从设备上通过discard操作丢弃的数据量,单位是扇区数,kB 或者 mB。 | 反映系统当前SSD Trim、空间回收类操作的吞吐量,数值越高说明当前系统正在大量释放磁盘空闲块 |
| 17 | drqm/s | The number of discard requests merged per second that were queued to the device. | 每秒合并的丢弃(Discard/TRIM)请求数量。 | “合并”的概念当文件系统或应用程序发起多个相邻或连续的 Discard 请求时,Linux内核的 I/O 调度器会将这些小的、相邻的请求合并为一个更大的请求发送给底层块设备。 |
| 18 | %drqm | The percentage of discard requests merged together before being sent to the device. | 合并请求的百分比=被合并的请求数量/总的请求数量。比如 1 秒钟内来了 100 个请求,其中 30 个请求 删除的是连续的磁盘空间,那么这 30 个请求就会被合并成 1 个,有 29 个请求被合并了。删除的请求数就是 70+1=71 个。%drqm = 29/100 = 29%。 | |
| 19 | d_await | The average time(in millsecodes) for discard requests issued to the deivice to be served.This includes the time spent by the requests in queue and the time spent servcing them. | 表示设备丢弃请求的平均服务时间(单位为毫秒)。该数值包含了两个部分: + 请求在队列中等待的时间。 + 实际 servicing(处理)请求所花费的时间。 | |
| 20 | dareq-sz | The average size(in kibibytes) of the discard requests that were issued to the device. | 丢弃请求的平均大小,以 KiB 为计量单位 | |
| 21 | aqu-sz | The average queue length of the requests that were issued to the device.Note:In previous versions,this field was know as avgqu-sz. | I/O 队列的平均长度。 | |
| 22 | %util | Percentage of elapsed time during which I/O requests were issued to the device (bandwidth utilization for the device).Device saturation occurs when this value is close to 100% for devices serving requests serially.But for devices serving requests in parallel,such as RAID arrays and modern SSDS,this number does not reflect their performance limits. | 设备在时间上的使用占用率。对于机械硬盘这种只能顺序写入的磁盘,这个值 100%代表磁盘性能已经达到了极限。但是对于可以并行写入的设备,比如 RAID 或者 SSD 盘 是支持并行写入的,只能代表一段时间内一直有内容在写入磁盘,并不代表达到了磁盘性能的上限 |
一般我会用iostat -xt 3 2的形式,代表了每 3 秒钟打印一次 ,连续打印 2 次,每次把时间打印出来。
三、磁盘性能瓶颈的判断依据
不能只看iostat -x 的 %util,因为这个参数仅代表了单位时间内,磁盘读,写,丢弃操作所占的时间比例,在 这个时间内,如果是支持并行操作的磁盘,还可以通过扩充并行度的方式提升性能。
要结合 await(r_await,w_await,d_await) 和 aqu-sz 一起看,瓶颈是说磁盘处理不了更多的请求,过多的请求就会在队列里堆积,会出现 aqu-sz 持续增长的情形,由于排队的请求数量增多,会导致排队时间越来越长,进而致 await 持续增长。所以如果观察到 await 和 aque-sz 一起增长,就可以确定出现了磁盘 I/O 性能瓶颈。
下图是一个出现I/O瓶颈的具体例子:
上面的截图可以看到:
- cpu 的 %iowait 越来越高,cpu 等待 io 的时间越来越长
- sda 的 w_wait 越来越高,写操作处理时间越来越长
- sda 的 wareq-sz 越来越高,排队的请求越来越多
说明 sda 这块盘出现了 I/O 瓶颈。