Linux下磁盘分析
一、基本介绍
磁盘信息查看
df -h
:磁盘空间信息
[root@localhost ~]# df -h
文件系统 容量 已用 可用 已用% 挂载点
/dev/mapper/rhel-root 17G 7.7G 9.2G 46% /
devtmpfs 896M 0 896M 0% /dev
tmpfs 912M 144K 912M 1% /dev/shm
tmpfs 912M 17M 895M 2% /run
tmpfs 912M 0 912M 0% /sys/fs/cgroup
/dev/sda2 1014M 165M 850M 17% /boot
/dev/sda1 200M 9.5M 191M 5% /boot/efi
tmpfs 183M 20K 183M 1% /run/user/0
fdisk -l
:磁盘分区信息
[root@localhost ~]# fdisk -l /dev/sda
WARNING: fdisk GPT support is currently new, and therefore in an experimental phase. Use at your own discretion.
磁盘 /dev/sda:21.5 GB, 21474836480 字节,41943040 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:gpt
# Start End Size Type Name
1 2048 411647 200M EFI System EFI System Partition
2 411648 2508799 1G Microsoft basic
3 2508800 41940991 18.8G Linux LVM
磁盘性能指标
- IOPS: (Input/Output Per Second),每秒IO操作次数。处理器单位时间内能处理的I/O请求数量,尤其在随机读写应用中,该指标非常重要。
- IO带宽: 单位时间内操作数据的数量,也可以说是单位时间磁盘I/O的流量。在顺序读写应用中,该指标非常重要。IO带宽=IOPS*单次IO请求量。
特殊磁盘文件
-
/dev/null : 在类Unix系统中,/dev/null,或称空设备,是一个特殊的设备文件,它丢弃一切写入其中的数据(但报告写入操作成功),读取它则会立即得到一个EOF。 在程序员行话,尤其是Unix行话中,/dev/null 被称为位桶(bit bucket)或者黑洞(black hole)。空设备通常被用于丢弃不需要的输出流,或作为用于输入流的空文件。这些操作通常由重定向完成。
-
/dev/zero : 在类UNIX 操作系统中, /dev/zero 是一个特殊的文件,当你读它的时候,它会提供无限的空字符(NULL, ASCII NUL, 0x00)。 其中的一个典型用法是用它提供的字符流来覆盖信息,另一个常见用法是产生一个特定大小的空白文件。BSD就是通过mmap把/dev/zero映射到虚地址空间实现共享内存的。可以使用mmap将/dev/zero映射到一个虚拟的内存空间,这个操作的效果等同于使用一段匿名的内存(没有和任何文件相关)。
二、分析工具和命令
SMART读取smartctl
smartctl -A /dev/sda
: 查看SMART信息 (SMART是硬盘内部关于硬盘健康度的信息)
监控io状态iostat
iostat -d 2 10
: 每2秒采样1次,共采样10次
使用例子如下:
[root@localhost ~]# iostat -d 2 10
Linux 3.10.0-514.el7.x86_64 (localhost.localdomain) 2017年09月14日 _x86_64_ (1 CPU)
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
fd0 0.00 0.00 0.00 28 0
sda 20.06 571.34 45.83 106141320 8514201
scd0 0.00 0.00 0.00 74 0
dm-0 15.59 340.03 39.69 63169947 7374396
dm-1 1.96 1.73 6.12 320756 1137596
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
fd0 0.00 0.00 0.00 0 0
sda 637.16 2546.45 4.37 4660 8
scd0 0.00 0.00 0.00 0 0
dm-0 0.00 0.00 0.00 0 0
dm-1 1.09 0.00 4.37 0 8
更复杂的例子如下:
[root@localhost Documents]# iostat -xmt /dev/sda
avg-cpu:%user %nice %system %iowait %steal %idle
1.89 0.23 0.90 2.20 0.00 94.78
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.35 1.54 15.24 2.82 0.46 0.05 57.31 0.47 26.23 10.91 109.12 1.76 3.18
该命令参数如下:
-C 显示CPU使用情况
-d 显示磁盘使用情况
-k 以 KB 为单位显示
-m 以 M 为单位显示
-N 显示磁盘阵列(LVM) 信息
-n 显示NFS 使用情况
-p[磁盘] 显示磁盘和分区的情况
-t 显示终端和CPU的信息
-x 显示详细信息
-V 显示版本信息
该命令信息解读如下:
rrqm/s: 每秒进行 merge 的读操作数目。即 delta(rmerge)/s
wrqm/s: 每秒进行 merge 的写操作数目。即 delta(wmerge)/s
r/s: 每秒完成的读 I/O 设备次数。即 delta(rio)/s
w/s: 每秒完成的写 I/O 设备次数。即 delta(wio)/s
rsec/s: 每秒读扇区数。
wsec/s: 每秒写扇区数。
rMB/s: 每秒读M字节数。
wMB/s: 每秒写M字节数。
avgrq-sz: 平均每次设备I/O操作的数据大小 (扇区)。delta(rsect+wsect)/delta(rio+wio)
avgqu-sz: 平均I/O队列长度。即 delta(aveq)/s/1000 (因为aveq的单位为毫秒)。
await: 平均每次设备I/O操作的等待时间 (毫秒)。即 delta(ruse+wuse)/delta(rio+wio)
svctm: 平均每次设备I/O操作的服务时间 (毫秒)。即 delta(use)/delta(rio+wio)
%util: 一秒中有百分之多少的时间用于 I/O 操作,或者说一秒中有多少时间 I/O 队列是非空的。
坏道检测badblocks
badblocks [-svw][-b <区块大小>][-o <输出文件>][磁盘装置][磁盘区块数][启始区块]
该命令参数如下:
-b<区块大小> 指定磁盘的区块大小,单位为字节。
-o<输出文件> 将检查的结果写入指定的输出文件。
-s 在检查时显示进度。
-v 执行时显示详细的信息。
-w 在检查时,执行写入测试。
[磁盘装置] 指定要检查的磁盘装置。
[磁盘区块数] 指定磁盘装置的区块总数。
[启始区块] 指定要从哪个区块开始检查。
使用例子如下:
[root@localhost ~]# badblocks -v /dev/sda
正在检查从 0 到 20971519的块
Checking for bad blocks (read-only test): done
Pass completed, 0 bad blocks found. (0/0/0 errors)
读取速度验证hdparm
hdparm -tT /dev/sda
:对磁盘sda的读取速度测试
[root@localhost ~]# hdparm -t /dev/sda
/dev/sda:
Timing buffered disk reads: 1310 MB in 3.02 seconds = 433.65 MB/sec
块数据拷贝dd
dd if=/dev/sda iflag=direct bs=4k of=/dev/zero
:对磁盘进行块拷贝,结合iostat可以观察磁盘性能
[root@localhost ~]# dd if=/dev/sda iflag=direct bs=4k of=/dev/zero
^C记录了1077066+0 的读入
记录了1077065+0 的写出
4411658240字节(4.4 GB)已复制,93.9845 秒,46.9 MB/秒
参数详解如下:
if =输入文件(或设备名称)。
of =输出文件(或设备名称)。
ibs = bytes 一次读取bytes字节,即读入缓冲区的字节数。
skip = blocks 跳过读入缓冲区开头的ibs*blocks块。
obs = bytes 一次写入bytes字节,即写入缓冲区的字节数。
bs = bytes 同时设置读/写缓冲区的字节数(等于设置ibs和obs)。
cbs = byte 一次转换bytes字节。
count = blocks 只拷贝输入的blocks块。
实用例子如下(将一个软盘拷贝到另一个软盘):
要把一张软盘的内容拷贝到另一张软盘上,利用/tmp作为临时存储区。把源盘插入驱动器中,输入下述命令:
$ dd if =/dev/fd0 of = /tmp/tmpfile
拷贝完成后,将源盘从驱动器中取出,把目标盘插入,输入命令:
$ dd if = /tmp/tmpfile of =/dev/fd0
软盘拷贝完成后,应该将临时文件删除:
$ rm /tmp/tmpfile
性能检测fio
fio --ioengine=libaio --randrepeat=0 --norandommap --thread --direct=1 --stonewall --group_reporting --name=mytest --ramp_time=60 -runtime=600 --numjobs=8 --iodepth=32 --filename=/dev/sda --rw=randread --bs=4k
- filename=/dev/sda 测试文件名称,通常为对应盘符。
- direct=1 1表示无buffer,测试更真实;0表示有buffer
- rw=randwrite 测试随机写的I/O,randwrite随机写,randread随机读,randrw随机读写,read顺序读,write顺序写,rw顺序读写。
- bs=16k 单次io的块文件大小为16k。
- bsrange=512-2048 同上,提定数据块的大小范围。
- size=5g 本次的测试文件大小为5g。
- numjobs=30 本次的测试线程为30。
- runtime=1000 测试时间为1000秒,如果不写则一直将5g文件操作完为止。
- ioengine=psync io引擎方式,sync基于read/write/lseek;psync基于pread/pwrite;vsync基于readv/writev;libaio异步io方式。
- rwmixwrite=30 在混合读写的模式下,写占30%。
- iodepth=32 io深度,表示io请求队列深度。
- group_reporting 关于显示结果的,汇总每个进程的信息。
测试例子如下:
顺序读==》
[root@localhost ~]# fio --ioengine=libaio --randrepeat=0 --norandommap --thread --direct=1 --stonewall --group_reporting --name=mytest --ramp_time=60 -runtime=10 --numjobs=8 --iodepth=32 --filename=/dev/sda --rw=read --bs=4k
mytest: (g=0): rw=read, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=32
...
fio-2.1.10
Starting 8 threads
Jobs: 8 (f=8): [RRRRRRRR] [100.0% done] [107.6MB/0KB/0KB /s] [27.5K/0/0 iops] [eta 00m:00s]
mytest: (groupid=0, jobs=8): err= 0: pid=60579: Fri Sep 15 09:29:49 2017
read : io=1108.1MB, bw=113388KB/s, iops=28322, runt= 10015msec
slat (usec): min=0, max=162740, avg=137.77, stdev=3048.36
clat (usec): min=38, max=144251, avg=9064.08, stdev=10589.85
lat (usec): min=173, max=144279, avg=9088.37, stdev=10626.34
clat percentiles (usec):
| 1.00th=[ 644], 5.00th=[ 1576], 10.00th=[ 2512], 20.00th=[ 3184],
| 30.00th=[ 3568], 40.00th=[ 4384], 50.00th=[ 5344], 60.00th=[ 6112],
| 70.00th=[ 8512], 80.00th=[12992], 90.00th=[20864], 95.00th=[28288],
| 99.00th=[51968], 99.50th=[72192], 99.90th=[88576], 99.95th=[90624],
| 99.99th=[144384]
bw (KB /s): min= 0, max=24233, per=11.84%, avg=13427.62, stdev=4084.97
lat (usec) : 50=0.02%, 100=0.01%, 250=0.04%, 500=0.12%, 750=1.23%
lat (usec) : 1000=0.51%
lat (msec) : 2=6.25%, 4=28.22%, 10=37.94%, 20=14.82%, 50=9.78%
lat (msec) : 100=1.13%, 250=0.02%
cpu : usr=0.55%, sys=68.72%, ctx=39607, majf=0, minf=271
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=997.7%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
issued : total=r=283646/w=0/d=0, short=r=0/w=0/d=0
latency : target=0, window=0, percentile=100.00%, depth=32
Run status group 0 (all jobs):
READ: io=1108.1MB, aggrb=113387KB/s, minb=113387KB/s, maxb=113387KB/s, mint=10015msec, maxt=10015msec
Disk stats (read/write):
sda: ios=2373225/31, merge=454568/9, ticks=673392/784, in_queue=674225, util=98.88%
随机读==》
[root@localhost ~]# fio --ioengine=libaio --randrepeat=0 --norandommap --thread --direct=1 --stonewall --group_reporting --name=mytest --ramp_time=60 -runtime=10 --numjobs=8 --iodepth=32 --filename=/dev/sda --rw=randread --bs=4k
mytest: (g=0): rw=randread, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=32
...
fio-2.1.10
Starting 8 threads
Jobs: 8 (f=8): [rrrrrrrr] [100.0% done] [2057KB/0KB/0KB /s] [514/0/0 iops] [eta 00m:00s]
mytest: (groupid=0, jobs=8): err= 0: pid=60730: Fri Sep 15 09:41:56 2017
read : io=22328KB, bw=2138.1KB/s, iops=510, runt= 10439msec
slat (usec): min=0, max=860464, avg=12775.29, stdev=58227.58
clat (usec): min=144, max=1722.2K, avg=472987.62, stdev=251025.20
lat (usec): min=145, max=1722.2K, avg=486547.98, stdev=257280.28
clat percentiles (msec):
| 1.00th=[ 6], 5.00th=[ 97], 10.00th=[ 165], 20.00th=[ 269],
| 30.00th=[ 343], 40.00th=[ 396], 50.00th=[ 449], 60.00th=[ 506],
| 70.00th=[ 562], 80.00th=[ 660], 90.00th=[ 807], 95.00th=[ 938],
| 99.00th=[ 1156], 99.50th=[ 1237], 99.90th=[ 1336], 99.95th=[ 1532],
| 99.99th=[ 1729]
bw (KB /s): min= 0, max= 506, per=11.65%, avg=249.07, stdev=119.76
lat (usec) : 250=0.17%, 500=0.11%, 750=0.02%
lat (msec) : 2=0.09%, 4=0.24%, 10=0.77%, 20=1.14%, 50=0.92%
lat (msec) : 100=2.21%, 250=13.12%, 500=42.48%, 750=29.10%, 1000=10.67%
lat (msec) : 2000=3.60%
cpu : usr=0.12%, sys=0.38%, ctx=6217, majf=0, minf=271
IO depths : 1=0.1%, 2=0.3%, 4=0.6%, 8=1.2%, 16=2.4%, 32=731.4%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
issued : total=r=5334/w=0/d=0, short=r=0/w=0/d=0
latency : target=0, window=0, percentile=100.00%, depth=32
Run status group 0 (all jobs):
READ: io=22328KB, aggrb=2138KB/s, minb=2138KB/s, maxb=2138KB/s, mint=10439msec, maxt=10439msec
Disk stats (read/write):
sda: ios=39249/76, merge=2/26, ticks=11050804/17575, in_queue=11071871, util=100.00%
read栏数据含义如下:
io= 执行了多少M的IO
bw= 平均IO带宽
iops= IOPS
runt= 线程运行时间
slat 提交延迟
clat 完成延迟
lat响应时间