IT基础架构中不管系统运维人员还是解决方案技术支持人员,都比较关注系统的性能以及稳定性。存储性能主要指标为IOPS,传输速度以及IO响应时间。本文针对存储IOPS性能测试方式以及常见的性能区别进行描述汇总交流。
对于性能测试,一般有两种方法:
1.使用业内比较认可的性能测试工具,比如IOMeter、fio、iozone等。这类工具一般是开源的,应用范围很广泛,使用它们的一个好处是可以快速和其他存储产品做横向对比。哪怕大家是在不同时间、不同地点、不同环境测试的,但只要参数设置差不多,就可以拿来简单对比(如果要做完整对比,必须放在同样的环境中测试)。不足之处是它们只能按照预定义的模式机械测试,大多数情况下无法真实反应实际应用环境的IO模式。
2.直接在真实的应用环境中进行性能测试。这种方法测出来的结果,针对特定的场景,具有权威的参考性。不足之处就是搭建环境可能比较麻烦,每个应用的依赖环境都不一样。即使是同样的存储设备,在不同的应用场景,其性能差异也很大。所以这种方法能反应存储产品在特定场景下的实际性能,但有时候并不能确定存储产品的普遍性能。
IOPS(IO per Second)
IOPS即IO系统每秒所执行IO操作的次数,是一个重要的用来衡量系统IO能力的一个参数。对于单个磁盘组成的IO系统来说,计算它的IOPS不是一件很难的事情,只要我们知道了系统完成一次IO所需要的时间的话我们就能推算出系统IOPS来。
现在我们就来推算一下磁盘的IOPS,假设磁盘的转速(Rotational Speed)为15K RPM,平均寻道时间为5ms,最大传输速率为40MB/s(这里将读写速度视为一样,实际会差别比较大)。
对于磁盘来说一个完整的IO操作是这样进行的:当控制器对磁盘发出一个IO操作命令的时候,磁盘的驱动臂(Actuator Arm)带读写磁头(Head)离开着陆区(Landing Zone,位于内圈没有数据的区域),移动到要操作的初始数据块所在的磁道(Track)的正上方,这个过程被称为寻址(Seeking),对应消耗的时间被称为寻址时间(Seek Time);但是找到对应磁道还不能马上读取数据,这时候磁头要等到磁盘盘片(Platter)旋转到初始数据块所在的扇区(Sector)落在读写磁头正上方的之后才能开始读取数据,在这个等待盘片旋转到可操作扇区的过程中消耗的时间称为旋转延时(Rotational Delay);接下来就随着盘片的旋转,磁头不断的读/写相应的数据块,直到完成这次IO所需要操作的全部数据,这个过程称为数据传送(Data Transfer),对应的时间称为传送时间(Transfer Time)。完成这三个步骤之后一次IO操作也就完成了。
在我们看硬盘厂商的宣传单的时候我们经常能看到3个参数,分别是平均寻址时间、盘片旋转速度以及最大传送速度,这三个参数就可以提供给我们计算上述三个步骤的时间。
第一个寻址时间Tseek,考虑到被读写的数据可能在磁盘的任意一个磁道,既有可能在磁盘的最内圈(寻址时间最短),也可能在磁盘的最外圈(寻址时间最长),所以在计算中我们只考虑平均寻址时间,也就是磁盘参数中标明的那个平均寻址时间,寻道时间Tseek是指将读写磁头移动至正确的磁道上所需要的时间。寻道时间越短,I/O操作越快,目前磁盘的平均寻道时间一般在3-15ms。
第二个旋转延时,和寻址一样,当磁头定位到磁道之后有可能正好在要读写扇区之上,这时候是不需要额外额延时就可以立刻读写到数据,但是最坏的情况确实要磁盘旋转整整一圈之后磁头才能读取到数据,所以这里我们也考虑的是平均旋转延时,旋转延迟取决于磁盘转速,通常使用磁盘旋转一周所需时间的1/2表示。比如,7200 rpm的磁盘平均旋转延迟大约为60*1000/7200/2 = 4.17ms,而转速为15000 rpm的磁盘其平均旋转延迟约为2ms。
第三个传送时间Ttransfer,是指完成传输所请求的数据所需要的时间,它取决于数据传输率,其值等于数据大小除以数据传输率。这个时间就是IO Size Max Transfer Rate。目前IDE/ATA能达到133MB/s,SATA II可达到300MB/s的接口数据传输率,数据传输时间通常远小于前两部分时间。
因此理论上可以计算出磁盘的最大IOPS,即IOPS = 1000 ms/ (Tseek + Troatation),忽略数据传输时间。假设磁盘平均物理寻道时间为3ms, 磁盘转速为7200,10K,15K rpm,则磁盘IOPS理论最大值分别为:
IOPS = 1000 (3 + 60000/7200/2) = 140
IOPS = 1000 (3 + 60000/10000/2) = 167
IOPS = 1000 (3 + 60000/15000/2) = 200
需要注意的是,上述计算中磁盘平均寻道时间的取值对计算结果的有较大的影响;同时为了提升磁盘的IO速度,所有的磁盘都会带有缓存,此外,机械硬盘性能还受到IO模型、磁盘数据密度、盘片直径、数据物理分布等因素的影响。并且随着技术的发展,传统机械硬盘引入了硬盘cache、TCQ/NCQ排序等技术对读写进行加速。因此在较大压力下,机械硬盘的实际最高性能是大于理论计算值的。
对于SSD盘,性能的差异主要在于存储单元架构的不同。SLC(单阶存储单元)优于MLC(多阶存储单元)。同种架构下,以e开头的企业版性能优于不以e开头的普通版。简单来说,eSLC > SLC > eMLC > MLC。
磁盘RAID组IOPS
通常我们在使用存储的时候,都是把多个磁盘建成一个Raid,那么这个由多个磁盘构成的RAID的IOPS就跟我们采用的RAID级别有很大关系,比如对于RAID5,一旦条带上的任意磁盘的数据发生改变,都会重新计算校验位。
无论是那种RAID级别,磁盘的读取性能都是所有磁盘之和。所以可以得出下面的读取IOPS:read IOPS = disk_IOPS/(1-disk_buffer_read_hit_ratio)*disk_num
但是不同RAID级别,磁盘的写性能则会由于不同类型的数据冗余影响实际写的数量,这种由于冗余数据带来的额外开销称为写惩罚penalty,RAID 0无RAID 惩罚、RAID 1/ 10写惩罚是2、RAID 5是4、RAID 6是6。
write IOPS =disk_IOPS/(1-disk_buffer_write_hit_ratio)*disk_num/ penalty
假设组成RAID的单个磁盘的随机读写的IOPS为140,读写缓存命中率都为10%,组成阵列的磁盘个数为4。这样RAID的读IOPS:
read IOPS = disk_IOPS/(1-disk_buffer_read_hit_ratio)*disk_num =140/(1-10%)*4 = 622
写入IOPS:
RAID总IOPS=写入IOPS+读IOPS。
磁盘阵列IOPS
磁盘阵列为了进一步提升性能,在其控制器上一般都会再加上cache缓存,有的还有第二级的缓存(Flash Memory/ Disks),这样一来整个阵列和其中某个RIAD的IOPS就变得难以计算。
很多厂商公布的那些非常高的IOPS数据实际上是将被测存储系统配置了尽量多的小容量、高转速磁盘且每个磁盘装载数据量不多、设置为RAID10时测出的100%顺序读(Sequential Read)IOPS的最大值。而且很多厂商在公布上述100%顺序读(Sequential Read)IOPS时还隐去了“100%顺序读”字样,笼统地称为IOPS。但多数用户实际使用的环境既有顺序读写、也有随机读写操作;传输数据块尺寸大小都有;为了有效利用存储系统的存储容量,很多用户都采用RAID5,而且尽量使用大容量磁盘来减少磁盘数量,以少占存储系统的宝贵槽位空间。因此厂商测试环境得到的100%顺序读(Sequential Read)IOPS指标完全不能代表该存储产品在用户实际应用环境下的性能。这就是厂商公布的IOPS很高,而产品在用户实际使用环境中性能却很差的原因。
幸运的是我们还有SPC和SPC-1 IOPS™可以信任和参考。SPC的全称是Storage Performance Council,它的成员由几乎全部的国外存储厂商和部分大学、研究机构组成,SPC是一个非赢利的组织,其使命是定义、标准化存储系统的基准测试,并提升存储系统基准测试的知名度、扩展其影响,使之成为计算机行业最具权威性的存储性能测试结果,使计算机用户可以不受现存混乱的各种存储性能测试结果的影响。目前SPC的SPC-1基准测试主要是针对随机I/O应用环境的,SPC-2基准测试主要是针对顺序I/O应用环境的。SPC-1基准测试很好地模拟了OLTP、数据库和e-mail等真实应用环境,使SPC-1基准测试结果具有很高权威性和可比性。各存储厂商的SPC-1基准测试报告中列明了进行测试的存储系统配置。
但是要注意的是,这些测试结果我们不应该直接使用,因为测试的配置和我们时间项目中的配置肯定不同,而且SPC-1/ 2也是个系统最大性能值。所以其最重要的意义在于它使我们知道这种磁盘阵列在某种配置下,阵列的实测IOPS跟我们通过上述IOPS中介绍的方法计算出来的总IOPS理论值之间的比例,这个比例(我称为提升因子)代表了阵列中的缓存对IO起到的提升作用。换句话说,以后我们在对阵列中RAID的IOPS理论计算中可以乘上这个比例。有些厂商也直接告诉你这个因子,比如说NetApp就宣称采用PAM缓存卡可降低75%的读IO,WAFL写优化可降低50%的写IO等等,这里的1/(1-75)%和1/(1-50%)就可以看作提升因子,只不过可信度有多少就不知道了。
传输速度(Transfer Rate)/吞吐率(Throughput)
现在我们要说的传输速度(或吞吐率)不是磁盘上所表明的最大传输速度或者说理想传输速度,而是磁盘在实际使用的时候从磁盘系统总线上流过的数据量。有了IOPS数据之后我们是很容易就能计算出对应的传输速度的(Transfer Rate) = IOPS * IO Size,可以看出实际上的传输速度是很小的,对总线的利用率也是非常的小。
这里一定要明确一个概念,那就是尽管上面我们使用IOPS来计算传输速度,但是实际上传输速度和IOPS是没有直接关系,在没有缓存的情况下它们共同的决定因素都是对磁盘系统的访问方式以及单个IO的大小。对磁盘进行随机访问时候我们可以利用IOPS来衡量一个磁盘系统的性能,此时的传输速度不会太大;但是当对磁盘进行连续访问时,此时的IOPS已经没有了参考的价值,这个时候限制实际传输速度却是磁盘的最大传输速度。因此在实际的应用当中,只会用IOPS来衡量小IO的随机读写的性能,而当要衡量大IO连续读写的性能的时候就要采用传输速度而不能是IOPS了。
IO响应时间(IO Response Time)
IO响应时间也被称为IO延时(IO Latency),IO响应时间就是从操作系统内核发出的一个读或者写的IO命令到操作系统内核接收到IO回应的时间,注意不要和单个IO时间混淆了,单个IO时间仅仅指的是IO操作在磁盘内部处理的时间,而IO响应时间还要包括IO操作在IO等待队列中所花费的等待时间。
随着系统实际IOPS越接近理论的最大值,IO的响应时间会成非线性的增长,越是接近最大值,响应时间就变得越大,而且会比预期超出很多。一般来说在实际的应用中有一个70%的指导值,也就是说在IO读写的队列中,当队列大小小于最大IOPS的70%的时候,IO的响应时间增加会很小,相对来说让人比较能接受的,一旦超过70%,响应时间就会戏剧性的暴增,所以当一个系统的IO压力超出最大可承受压力的70%的时候就是必须要考虑调整或升级了
因此使用同样的存储设备,同样的硬盘,当如下条件变化时,性能差异可能会很明显。
1.读和写。理论上,机械硬盘的顺序读写性能差不多。但在不同的场景,同样硬盘的读写性能是有差异的。因为写数据的时候,缓存的作用更大,所以写的性能可能更好。但如果使用RAID5,因为写数据有写惩罚,所以在其他条件相同时,读的话性能更好。SSD的读写参数天生就不一样,因为写数据会引起块擦除,所以往往读更快,尤其是随机读。
2.顺序IO和随机IO。对于机械硬盘,毫无疑问,顺序读写比随机读写快很多,因为顺序读写少了很多寻道时间,其速度比随机读写高出1到2个数量级。所以,传统的存储需要使用缓存算法(包括按扇区地址的排序以及预读等)来减少寻道时间,提高性能。对于SSD,顺序读写和随机读写差别不是那么大,但是顺序读写一般来说会比随机读写快。实际应用中,纯随机读写很少,即使在文件系统中拷贝大文件,也有一些相对随机的操作,比如修改元数据,跳过一些被占用的扇区等。所以,如何模拟应用程序的随机度,是一个比较头疼的问题。
3.块大小(blocksize)。如果单次IO写入的数据块比较大,比如超过了1MB,性能显然比较好。即使是机械硬盘纯随机写入1MB也如此——单个数据块往往是一次性提交给驱动的,每个块内部的数据一般也是连续的。每秒只需要少量的IO能过去,就能获得较大的带宽,因为带宽=IO大小*IO数,IO数虽然不多,但IO平均大小较大。但也有例外。如果把块大小设置成很大(比如1GB),在系统里面肯定会被拆分成较小的IO发下去,所以性能不会有进一步改善,在应用程序不够完善时反而会导致额外的问题(比如直接就给分配了1GB的内存导致内存有可能不足)。即使前面说的1MB的IO,在很多系统中,也可能会被拆分成2个或者几个IO发下去。如果是顺序读写,4KB的小IO,在操作系统内部也可能会被合并成大的IO,所以这种情况下,性能不会太差,但合并IO等步骤本身需要消耗资源,所以性能也不会太好。需要注意的是,有些时候,评判性能标准不是按读写带宽来看,而是按照每秒的IO数(IOPS)来看。显然,块大小的设置就比较难提高IOPS的值了。
4.缓存的影响。当读写缓存比较大时,性能显然会好一些。尤其是进行随机写测试,在写缓存比较大时,刚开始的性能值会非常大(其实就是写到内存的速度),到后来一下子降下来。因此,为了避开缓存的的影响,有时候需要测试direct IO。但在大多数应用场景下,缓存都是需要使用的,我们得了解在缓存起作用的情况下的性能,同时又要跳开刚开始测试阶段的不稳定性能值,那我们可以设置相应的时间参数,不把最开始的一段时间的性能值统计进去。IOMeter的Ramp Up Time就是为这个准备的。有人拿同样的配置测试随机读写,两次测出的值大不一样,其原因就有可能是没有把这个原因考虑进去。即使设置了Ramp Up Time,但其值太小,在缓存还没有写满的时候其时间就到了,也会统计得不准确。
5.同步IO和异步IO。同步IO是发一个IO,等确认完成之后,再发下一个IO。这是一个串行的过程。异步IO是发了一个IO,还没有完成,就发下一个IO,IO的处理过程是异步的。显然,异步IO的性能一般会好一些。IOMeter和fio等都能对它们进行测试。IOMeter有一个“# of Outstanding I/Os”的参数,用于设置可以同时发的异步IO的个数。如果要测试出比较好的性能,一般要用异步IO。
6.其他影响因子。太多了,无法一一列举。比如多线程、机械硬盘的外圈和内圈等。现在的机械硬盘内部结构很复杂,扇区的物理排布和硬盘的固件有关,但一般可以简单认为,机械硬盘的开始部分(扇区地址较小部分,或者简单认为是外圈)比结尾部分(扇区地址较大部分,或者简单认为是内圈)的速度要快。
因为有如此多的影响性能的因素,所以,也需要测试工具要提供众多参数来进行设置,以便精准地测试性能的原因。但实际的应用场景可能更复杂,有可能一会儿是大块的顺序读写,一会儿又变得更随机。如果我们能够精准预估应用程序读写存储的模式,理论上也可以用IOMeter等工具来模拟,无非是把配置写得比较复杂而已。但有时候很难预估它的读写模式,所以采用实际的应用环境更具有性能参考意义。因为实际应用环境搭建麻烦,所以,有时候会自己写一些测试工具,尽可能模拟应用场景,然后以比较简单的模式来进行测试,可以有更高的测试效率,以便不断改进系统。