机械硬盘随机IO慢的超乎你的想象

你们都知道硬盘的随机IO很慢,可是比顺序IO慢多少呢,不知道你是否有过数字上的直接对比。今天我来实际压测对比一下磁盘在顺序IO和随机IO不一样场景下的性能数据表现。经过今天的实验数据,你将能深入理解数据库事务中为何要用日志的方式来实现,为何索引中要用节点更大的B+树。sql

对于任何存储系统,性能指标无非就是带宽、延迟或IOPS。个人测试机器的硬盘配置是一个由7块300G万起色械磁盘组成的RAID5,压测工具使用的fio,压测过程当中,咱们固定几个参数:数据库

  • IO引擎咱们选择libaio
  • 为了不操做系统管理的PageCache内存对测试结果的干扰,使用direct参数绕开
  • 打开unified_rw_reporting,让结果中分别显示读和写
  • 为了保证测试相对准确,咱们运行时间设置为300s
  • 因为服务器敏感性,压测对象没有选择裸设备,用的文件,会有一点文件系统额外开销
  • 测试文件尺寸定义为100G,个人RAID卡缓存是1G,目的就是让它的命中率别过高
  • 调度策略咱们选择最最经常使用的noop
  • 打开refill_buffers,每次I/O提交后都从新生成测试文件数据片断,保证随机性
  • 按照RAID使用配置建议,关闭掉磁盘自带缓存

而后再对另外的参数进行动态调整,而后进行屡次对比测试缓存

  • 读写模式上,使用顺序读和随机读进行分别验证
  • 磁盘IO单位咱们使用扇区的整数倍,512 1K 2K ...
  • RAID卡预读策略,分别设置NORA(不开启预读)和RA(开启预读)来独立测试

顺序读取测试

咱们先来看一下顺序读取状况下,在该磁盘阵列的带宽表现,见图1:性能优化

图1 带宽表现

能够看到,当IO size比较小的时候,即便是顺序发起连续IO请求,带宽表现也不算给力,只有不到20MB/s。随着IO size增长的时候,带宽也上来了,最大可以达到1.2GB多。服务器

你们注意看下在NORA状况下,在128K增长到256K的时候,带宽忽然增长了不少,这是为啥呢?秘密在于个人RAID阵列里的条带大小是128K,当IO size为256K的时候,磁盘阵列才开始真正并行工做了。IO size小的时候,并不能发挥多盘优点。网络

/opt/MegaRAID/MegaCli/MegaCli64 -LDInfo -Lall -aALL
......
Strip Size          : 128 KB

另外就是对于顺序IO的状况,RA预取也能起到一些做用,在IO size在64k的时候就可以达到1.2GB的带宽。工具

咱们再来看延迟,见图2:oop

图2 延迟表现

咱们图中的单位是微秒-us,在《简单聊聊磁盘分区》中,我对磁盘耗时进行过理论上的估算,磁盘耗时主要在两个地方:性能

  • 寻道时间:3-15ms,这个耗时能够经过合理分区优化
  • 旋转延迟:万转磁盘这个延迟大概0-6ms

为何在图2实验结果里,延时却都很低,在IO size为512的时候,平均居然只有30us左右?其实顺序IO的状况下,RAID卡缓存命中率很高,其实绝大部分的读请求并无穿透到让磁盘的机械轴来工做。测试

咱们再来看IOPS,见图3:

图2 IOPS表现

在IO请求size正好为1个扇区大小的时候,磁盘阵列的IOPS表现最高,达到了3W屡次每秒。当IO size增长的时候,IOPS在逐步降低,但这时候,其实磁盘的吞吐是在增长的。

汇总一下,磁盘阵列在顺序IO的状况下表现仍是很不错的,缘由有三个:

  • 顺序IO的状况下,RAID卡的命中率高,尤为是设置了RAID预取
  • 单盘自己顺序IO也是磁盘工做最舒服的状态,由于节约了寻道的延时
  • 当IO超过RAID条状大小的时候,IO会分散到多块盘上并行处理

随机读取测试

咱们做为开发者使用磁盘的时候,可能不必定能保证永远都能让它工做在最舒服的状态,有些时候可能也必须得让它进行随机访问。因此咱们今天也试一下个人磁盘阵列在随机状况下的表现,对于fio工具来讲只须要设置rw参数为randread既可。不过IO size我只测试到了128就停了,由于再大了就越像顺序IO了。

咱们仍是先来看带宽,见图4:

图4 带宽表现

机械硬盘即便是组成了RAID阵列,并且还有缓存,貌似对随机IO也迫不得已。在随机IO的状况下,带宽吞吐糟糕透了,在IO size比较小的时候,居然只有零点几兆每秒。

咱们再来看延时,见图5:

图5 延迟表现

随机状况下延时基本都5ms左右,这就和咱们前面理论上的计算结果对上了。随机访问致使更多的请求真正穿透到了机械轴上。

再来看IOPS,这个指标也不好,也就是200左右吧。这个数据和图5的延迟造成了呼应,处理一次请求5ms左右,那么1秒可不就是只能处理200次左右么。因此硬盘厂家们每天给你吹风,说他家磁盘IOPS能达到几万几万。可是他们历来闭口不提随机IO状况下,其实特么的只有200。

图6 IOPS表现

你们看到了个人万起色械硬盘组成RAID5阵列,在顺序条件最好的状况下,带宽能够达到1GB/s以上,平均延时也很是低,最低只有20多us。可是在随机IO的状况下,机械硬盘的短板就充分暴露了,零点几兆的带宽,将近5ms的延迟,IOPS只有200左右。其缘由是由于

  • 随机访问直接让RAID卡缓存成了个摆设
  • 磁盘不能并行工做,由于个人机器RAID宽度Strip Size为128 KB
  • 机械轴也得在各个磁道之间跳来跳去。

理解了磁盘顺序IO时候的几十M甚至一个GB的带宽,随机IO这个真的是太可怜了。

结论

从上面的测试数据中咱们看到了机械硬盘在顺序IO和随机IO下的巨大性能差别。在顺序IO状况下,磁盘是最擅长的顺序IO,再加上Raid卡缓存命中率也高。这时带宽表现有几10、几百M,最好条件下甚至能达到1GB。IOPS这时候能有2-3W左右。 到了随机IO的情形下,机械轴也被逼的跳来跳去寻道,RAID卡缓存也失效了。带宽跌到了1MB如下,最低只有100K,IOPS也只有可怜巴巴的200左右。

若是你真正理解了以上实验中的数据,就能理解不少工程实践中的许多的事情。

复制文件夹:咱们都知道,在复制一个文件夹的时候,若是这个文件夹里面包含了许多堆碎文件,这时候复制起来很是慢。缘由就是这时候机械硬盘大几率都是在随机IO。怎么提升复制速度呢?很简单,就是把它们先打一个包。打包以后这个文件夹就变成一个大文件了,这时候再复制的话,磁盘就是执行的最擅长的顺序IO了,因此会快不少。

数据库事务:全部的数据库在实现事务的时候,都要保证写数据落盘成功才能返回。但为何他们几乎都是落盘到本身的事务日志文件里去就返回成功的,而不是直接写入到数据表文件里。这背后的缘由仍是磁盘读写性能问题,事务只须要保证数据落地成功就能够,至于写到哪里并不重要。写到数据文件中的话大几率就变成随机IO了。若是写到一个日志文件中,就是地地道道的顺序IO,性能就发挥到极致。

Mysql的B+树:在上面的数据中你们还能够看到,不管是顺序IO仍是随机IO,只要增长每次IO的单位,性能都会上涨。理解了这个,你就能真正理解为何Mysql是采用B+树当索引,而不是用其它的树了(好比二叉树)。由于B+树的节点更大,IO起来会让磁盘工做更舒服一些。

最后结尾我想分享一个5年前我在工程中实际性能优化的案例。当时接手了一个系统,要用数以百万级的用户imei,到Mysql中去查询用户的另外一个字符串id(clientid)数据。前开发的实现方式是传统的分批进行Mysql语句查询。这种实现下,且不说屡次的网络RTT耗时,单说Mysql查询,即便是有索引这时候也得须要进行大量的随机IO,由于用户imei是随机分布的。我采用的优化方式也很是简单,直接把Mysql用户整张用户表一次性经过顺序IO的方式读出来,load到内存中。在内存中用HashTable组织好,经过Hash的方式进行快速查询。最终耗时优化掉了90%以上。


file


开发内功修炼之硬盘篇专辑:


个人公众号是「开发内功修炼」,在这里我不是单纯介绍技术理论,也不仅介绍实践经验。而是把理论与实践结合起来,用实践加深对理论的理解、用理论提升你的技术实践能力。欢迎你来关注个人公众号,也请分享给你的好友~~~

相关文章
相关标签/搜索