Linux下磁盘分析

20 分钟阅读

一、基本介绍

磁盘信息查看

  • 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响应时间

fio官网地址

三、工具附件

Linux fio 2.1.10下载 Windows下磁盘分析工具HDTunePro