磁盘I/O性能优化的几个思路

虽然 I/O 的性能指标很多,相应的性能分析工具也有好几个,但理解了各种指标的含义后,你就会发现它们其实都有一定的关联 。
顺着这些关系往下理解,你就会发现,掌握这些常用的瓶颈分析思路,其实并不难 。
找出了 I/O 的性能瓶颈后,下一步要做的就是优化了,也就是如何以最快的速度完成 I/O操作,或者换个思路,减少甚至避免磁盘的 I/O 操作 。
本文,我就来说说,优化 I/O 性能问题的思路和注意事项 。
I/O基准测试按照我的习惯,优化之前,我会先问自己,I/O 性能优化的目标是什么?换句话说,我们观察的这些 I/O 性能指标(比如 IOPS、吞吐量、延迟等),要达到多少才合适呢?
事实上,I/O 性能指标的具体标准,每个人估计会有不同的答案,因为我们每个人的应用场景、使用的文件系统和物理磁盘等,都有可能不一样 。
为了更客观合理地评估优化效果,我们首先应该对磁盘和文件系统进行基准测试,得到文件系统或者磁盘 I/O 的极限性能 。
fio(Flexible I/O Tester)正是最常用的文件系统和磁盘 I/O 性能基准测试工具 。它提供了大量的可定制化选项,可以用来测试,裸盘或者文件系统在各种场景下的 I/O 性能,包括了不同块大小、不同 I/O 引擎以及是否使用缓存等场景 。
fio 的安装比较简单,你可以执行下面的命令来安装它:
# Ubuntuapt-get install -y fio# centosyum install -y fio安装完成后,就可以执行 man fio 查询它的使用方法 。
fio 的选项非常多,我会通过几个常见场景的测试方法,介绍一些最常用的选项 。这些常见场景包括随机读、随机写、顺序读以及顺序写等,你可以执行下面这些命令来测试:
#随机读fio -name=randread -direct=1 -iodepth=64 -rw=randread -ioengine=libaio -bs=4k -size=1G#随机写fio -name=randwrite -direct=1 -iodepth=64 -rw=randwrite -ioengine=libaio -bs=4k -size=1G#顺序读fio -name=read -direct=1 -iodepth=64 -rw=read -ioengine=libaio -bs=4k -size=1G -numjobs=#顺序写fio -name=write -direct=1 -iodepth=64 -rw=write -ioengine=libaio -bs=4k -size=1G -numjob在这其中,有几个参数需要你重点关注一下 。

  • direct,表示是否跳过系统缓存 。上面示例中,我设置的 1,就表示跳过系统缓存 。
  • iodepth,表示使用异步 I/O(asynchronous I/O,简称 AIO)时,同时发出的 I/O 请求上限 。在上面的示例中,我设置的是 64 。
  • rw,表示 I/O 模式 。我的示例中,read/write 分别表示顺序读 / 写,而randread/randwrite 则分别表示随机读 / 写 。
  • ioengine,表示 I/O 引擎,它支持同步(sync)、异步(libaio)、内存映射(mmap)、网络(net)等各种 I/O 引擎 。上面示例中,我设置的 libaio 表示使用异步I/O 。
  • bs,表示 I/O 的大小 。示例中,我设置成了 4K(这也是默认值) 。
  • filename,表示文件路径,当然,它可以是磁盘路径(测试磁盘性能),也可以是文件路径(测试文件系统性能) 。示例中,我把它设置成了磁盘 /dev/sdb 。不过注意,用磁盘路径测试写,会破坏这个磁盘中的文件系统,所以在使用前,你一定要事先做好数据备份 。
下面就是我使用 fio 测试顺序读的一个报告示例 。
read: (g=0): rw=read, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libfio-3.1Starting 1 processJobs: 1 (f=1): [R(1)][100.0%][r=16.7MiB/s,w=0KiB/s][r=4280,w=0 IOPS][eta 00m:00s]read: (groupid=0, jobs=1): err= 0: pid=17966: Sun Dec 30 08:31:48 2018read: IOPS=4257, BW=16.6MiB/s (17.4MB/s)(1024MiB/61568msec)slat (usec): min=2, max=2566, avg= 4.29, stdev=21.76clat (usec): min=228, max=407360, avg=15024.30, stdev=20524.39lat (usec): min=243, max=407363, avg=15029.12, stdev=20524.26clat percentiles (usec):|1.00th=[498],5.00th=[1020], 10.00th=[1319], 20.00th=[1713],| 30.00th=[1991], 40.00th=[2212], 50.00th=[2540], 60.00th=[2933],| 70.00th=[5407], 80.00th=[ 44303], 90.00th=[ 45351], 95.00th=[ 45876],| 99.00th=[ 46924], 99.50th=[ 46924], 99.90th=[ 48497], 99.95th=[ 49021],| 99.99th=[404751]bw (KiB/s): min= 8208, max=18832, per=99.85%, avg=17005.35, stdev=998.94, samples=1iops: min= 2052, max= 4708, avg=4251.30, stdev=249.74, samples=123lat (usec): 250=0.01%, 500=1.03%, 750=1.69%, 1000=2.07%lat (msec): 2=25.64%, 4=37.58%, 10=2.08%, 20=0.02%, 50=29.86%lat (msec): 100=0.01%, 500=0.02%cpu: usr=1.02%, sys=2.97%, ctx=33312, majf=0, minf=75IO depths: 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.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.0%, 64=0.1%, >=64=0.0%issued rwt: total=262144,0,0, short=0,0,0, dropped=0,0,0latency: target=0, window=0, percentile=100.00%, depth=64Run status group 0 (all jobs):READ: bw=16.6MiB/s (17.4MB/s), 16.6MiB/s-16.6MiB/s (17.4MB/s-17.4MB/s), io=1024MiB (1Disk stats (read/write):sdb: IOS=261897/0, merge=0/0, ticks=3912108/0, in_queue=3474336, util=90.09%


推荐阅读