服务器端性能测试判断磁盘瓶颈的方法

文章目录

  以前做性能测试的时候,磁盘瓶颈总是判断的不太准确,这两天仔细研究了一下,记录一下研究的结果。

一、主流磁盘结构

现在主流的磁盘结构有两种:

(一)、不划分逻辑卷的结构

bash 复制代码
物理磁盘(sda ssd/hdd)
    ↓
分区1(sda1) → 文件系统 → 挂载 /boot
    ↓
分区2(sda2) → 文件系统 → 挂载 /
    ↓
分区3(sda3) → 文件系统 → 挂载 /data

  比如把 sda 划分了 3 个分区,其中 1 个叫 sda1,格式化成 ext4 或 xfs 格式(文件系统),挂载到了/boot 目录下。

  这种结构在磁盘空间不足的时候扩展起来不方便,适合小的系统。具体的原因是要实现存储扩展需要连续的存储空间,但是很难把两块硬盘从物理上前后连起来形成连续的存储空间。

(二)、划分逻辑卷的结构

bash 复制代码
物理磁盘 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

bash 复制代码
[test@kylinv10 security]$ lsblk
NAME  					MAJ:MIN				RM			SIZE			R0			TYPE			MOUNTPOINT
sda						8:0					 0			100G			 0			disk
|-sda1					8:1					 0			1G			 	 0			part 			/boot
|-sda2					8:2				 	 0			99G				 0			part
  |-vg0-root			253:0				 0		 	91.1G			 0			lvm				/
  |-vg0-swap			253:1				 0     	 	7.9G			 0      	lvm				[swap]
  1. NAME磁盘名称,sda第一块物理磁盘;sda1/sda2磁盘分区;vg0‑root/vg0‑swapLVM 逻辑卷
  2. MAJ:MIN主 / 次设备号,内核识别硬件的编号
  3. RM是否可移动磁盘,0=本地硬盘,1=U盘/移动盘
  4. SIZE容量
  5. R0是否只读只读标志,0=可读写
  6. TYPE设备类型,disk物理磁盘,part普通分区,lvm 逻辑卷
  7. MOUNTPOINT挂载点,swap代表交换分区

(二)、查看磁盘结构命令二 pvdisplay

  这个命令需要 root 权限,一般用的比较少

bash 复制代码
[test@kylinv10 /]$ pvdisplay
--- Physical volume ---
PV Name						/dev/sdb
VG Name   					vg01
PV SIZE						31.43 TiB / not usable 4.00MiB
Allocatable					yes(but full)
PE Size						4.00MiB
Total PE						8240183
Free PE						0
Allocated PE				8240183
PV UUID           		Xoo**-**-**

--- Physical volume ---
PV Name						/dev/sdc
VG Name           			vg01
PV SIZE						31.43 TiB / not usable 4.00MiB
Allocatable					yes(but full)
PE Size						4.00MiB
Total PE					8240183
Free PE						0
Allocated PE				8240183
PV UUID           			Xoo**-**-**

  从上面可以看出来,我的机器上有两块大盘 /dev/sdb、/dev/sdc,都作为 PV 加入同一个卷组 vg01。两块盘大小完全一致:每块 31.43TiB,PE 默认 4MiB,两个 PV 的空间已经全部分配给了vg01,Free PE = 0,vg01 卷组已经没有可再分配给逻辑卷的空闲空间。

(三)、查看磁盘已经使用的容量 df -h

bash 复制代码
[test@kylinv10 /]$ df -h
文件系统						 		容量		已用		可用		已用%		挂载点
devtmpfs							3.9G		   0		3.9G		     0%		/dev
tmpfs								3.9G		 12K		3.9G			 1%		/dev/shm
tmpfs								3.9G		138M		3.8G			 4%		/run
tmpfs								3.9G		   0		3.9G			 0%		/sys/fs/cgroup
/dev/mapper/vg0-root	 			92G			9.3G		 82G			11%		/
tmpfs								3.9g		2.6K		3.9G			 1%		/tmp
/dev/sda1						 	1014M		529M		486M			53%		/boot
10.128.*.*/test_req					20G			1.2G		 19G			 6%  	/test_req
tmpfs								795M		   0		795M			 0%		/run/user/501
tmpfs								795M		   0		795M			 0%		/run/user/0
tmpfs								795M		   0		795M			 0%		/run/user/503

文件系统有三类,分别是 devtmpfs,tmpfs 和 带路径的存储盘。

第一类是devtmpfs内存存储,每次重启先清空后创建

  • 系统设备目录,存放磁盘、网卡、串口等硬件设备文件
  • 全部在内存,不消耗磁盘 ;容量约等于机器一半物理内存;0已用代表设备节点几乎不占存储。

第二类是tmpfs内存存储,重启清空

  • /dev/shm 共享内存;程序、Docker、数据库会用这块内存盘做共享内存通信。
  • /run:系统运行时目录,存 PID 文件、socket 套接字、服务临时状态。
  • /sys/fs/cgroup cgroup 相关挂载,内核用来限制进程 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

bash 复制代码
[test@kylinv10 /]$ ll /dev/mapper
总用量 0
crw------- 1 root root		10,236 6月 19 00:41 control
lrwxrwxrwx 1 root root			7	6月 19 00:41 vg0-root -> ../dm-0
lrwxrwxrwx 1 root root 			7	6月 19 00:41 vg0-swap -> ../dm-1

dev/dm‑0(dm‑X):内核真实设备 ,内核只认识这个编号;

/dev/mapper/vg0‑root人为做的软链接,别名,给人看的,方便识别卷组‑逻辑卷名字

  Linux 内核访问块设备,根本不认识 vg0‑root 这种人类命名。

  内核识别设备唯一标识:主设备号:次设备号

  device‑mapper 的主设备号固定是 253:

  • 253:0/dev/dm‑0
  • 253:1/dev/dm‑1

  内核、驱动、io 调度、磁盘调度策略,全部操作的是 dm‑0/dm‑1

  软链接 /dev/mapper/vg0‑root 只是文件系统层面的符号链接,内核根本不知道这个名字存在

  把这个软链接删掉,系统照样跑,只是人类不方便识别设备。

(五)、查看当前系统 I/O 状况 iostat -x

bash 复制代码
[test@kylinv10 /]$ iostat
Linux 4.19.90-89.4.v2401.ky10.x86_64(kylinv10)		2026 年 08 月 14 日		(4CPU)
avg-cpu: %user	%nice		%system		%iowait		%steal		%idle
          0.17	 0.00			 0.15			 0.00		  0.00		99.68

Divce	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-0	0.02	0.54	0	0	2.67	37.84	0.44 10.1	0	0	3.06	16.04	0	0	0	0	0	0	0	0.06
dm-1	0.01	0.53	0	0	2.67	37.84	0.44 10.1	0	0	3.06	16.04	0	0	0	0	0	0	0	0.06
sda	  0.03	0.53	0	0	2.67	37.84	0.44 10.1	0	0	3.06	16.04	0	0	0	0	0	0	0	0.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瓶颈的具体例子:

  上面的截图可以看到:

  1. cpu 的 %iowait 越来越高,cpu 等待 io 的时间越来越长
  2. sda 的 w_wait 越来越高,写操作处理时间越来越长
  3. sda 的 wareq-sz 越来越高,排队的请求越来越多
    说明 sda 这块盘出现了 I/O 瓶颈。
相关推荐
行百里er20 小时前
Spring Insight 里收到的 Span 是怎么存下来的
spring boot·spring·监控
行百里er2 天前
Spring Insight 里上报 Span 为什么用 JDK HttpClient 而不是 RestTemplate
spring boot·spring cloud·监控
SkyWalking中文站3 天前
Horizon UI 1.0 正式发布:SkyWalking 新一代控制台接棒 Booster
运维·监控·自动化运维
行百里er3 天前
BlockingQueue:异步批量上报
spring boot·spring cloud·监控
IT界的老黄牛3 天前
Prometheus TSDB 拆不出来、也存不了一年:4 条外部存储出路 + 容量测算
prometheus·时序数据库·监控·thanos·victoriametrics·remote_write
2601_962297254 天前
从前端角度浅谈性能
性能·用户体验·核心指标·rail模型·加载过程
千里马学框架4 天前
安卓系统性能优化高级实战开发专题--开机,app冷启动优化
android·智能手机·性能优化·framework·性能·开机优化·app冷启动优化
IT界的老黄牛5 天前
Jenkins 监控一条龙:接入、看板 9964、11 条告警规则直接抄走
jenkins·grafana·prometheus·监控·ci-cd·告警规则
SkyWalking中文站5 天前
SkyWalking 11 与 BanyanDB 0.11:在存储引擎内部实现 Trace 尾部采样
运维·监控·自动化运维
wardenlzr5 天前
车机Binder 线程池耗尽实战排查与内核内存原理深挖
binder·性能·车机