分布式文件系统读写性能分析

转自:http://blog.csdn.net/tonyfirst1/article/details/17440563  很有启迪意义。


   

概述:

分布式文件系统的后端存储一般都是许多磁盘,有物理磁盘、有磁盘阵列等。说到整个文件系统的读写性能,最后都要归于单个物理磁盘的性能。

 

单个物理磁盘性能特点:

l  顺序IO的性能好,因为不需要磁盘的寻道时间。

l  随机IO性能差,每秒的小块读写IOPS也就100左右。

l  IO请求长度越大,吞吐量越高。

l  由磁盘的物理结构限定,磁盘片外圈的IO性能好于内圈。

 

磁盘阵列是对许多磁盘的封装,性能特点虽然不像单个磁盘那么明显,但总体趋势还是相符合的。

 

无论是单个磁盘还是磁盘整列,我们都称为存储,存储主要有两项性能指标,吞吐量和IOPS。一般情况下,IOPS指的是小块IO的IOPS,吞吐量以大块IO来测量。

l  吞吐量:存储每秒处理的数据总量。

l  IOPS:存储每秒处理的IO请求总个数。

吞吐量和IOPS之间一般还是有一定的关联,存储的性能较好,IOPS越高,吞吐量就较高,反之亦然。IOPS越高,IO请求的响应时间就越短。另外无论是吞吐量还是IOPS都是IO越有顺序,就越高,反之越随机,就越低。

 

性能分析:

性能测试主要由几个因素组合来测试:读、写、IO长度、随机、顺序、线程数量。在这几个因素中,甚至还可以读写混合、顺序和随机混合等。随机小块决定了存储的最低性能,顺序大块决定了存储的最高性能。一般项目运用中,以多线程顺序IO为主。下文主要分析一下多线程顺序IO。

 

举一个分布式文件系统的一般使用情景:多个客户端以多线程顺序读写存储,如下图所示:

 

                                               网络(阻塞1)

                                  

 

         存储(阻塞2)                                                客户端

 

 

                                                 网络(阻塞3)

 

如图所示:一个线程发起一个IO请求,先经过网络发送到服务器。服务器发送给物理存储处理,最后答复处理结果给客户端。从图中可以看出,顺畅的网络、高性能的存储是整个系统性能的基础保障。

 

如何发挥存储的最佳性能?就说说吞吐量的事情。

 

l  吞吐量:

 

一句话说明:顺序大块,压榨存储使用率。只要能够以顺序大块使存储的使用率达到100%,这时便可以发挥出存储的最大吞吐量。

存储使用率100%,是指存储在任何时间都在干活,没有空闲时间。怎么才能达到这个目标呢?只要保证在存储排队的IO数持续>=1,那么存储的利用率就能达到100%。这对于吞吐量和IOPS都是适用的。

 

怎样才能保证存储上的IO排队数量大于1呢?

 

假设网络不是瓶颈的情况下,先看看客户端单线程同步IO能否实现。客户端单线程发起一个请求后,发送时在网络阻塞一次,应答时在网络阻塞一次,在这两个阻塞时间里面,存储上的IO队列长度必定为0,存储空闲。由此可见,客户端单线程是不能发挥出存储的最大吞吐量的,IOPS也一样。

 

单线不行,那肯定就是需要多个线程了。那么需要多少线程呢?

 

一个同步IO,假设在存储上耗时5ms,其他耗时(网络)也是5ms。这种情况下2个线程就可以保证存储上持续有一个IO在处理。试想一下,存储处理完毕一个IO后,这个IO 5ms后,又会到达存储排队,5ms时间恰好存储处理完了下一个IO,这样周而复始,完成了一个循环。

 

假设存储处理时间和网络处理时间不变的情况下,可以用下面这个公式来计算线程数量。

 

线程数量 = IO请求总时间 / 存储耗时。

 

上面的例子中,2 =10 / 5。

该公式仅供参考,并非定理准则。

其实对于IOPS来说,一样合乎上面的道理。

 

除开上面说的增加线程以外,还有另外一个办法可以保证存储上持续有一个IO处理,即使得存储利用达到100%。什么办法呢?异步。

 

l  异步IO(延迟写):

 

异步IO一般是针对写IO来说的,读IO并不适用。

 

试想下面的流程,一个IO到达网络时,网络(1)立即返回成功,客户端这时立即发起下一个IO请求。这时网络(1)至少有一个以上的IO在排队。按照上面的原理网络已经100%的干活了。继续,IO请求达到存储时,存储立即返回成功。这时网络(1),立即发起下一个IO请求,同样使得存储上排队的IO请求数量大于1,利用率达到100%。

 

这个情景中,若是存储的性能优于网络,就会出现这种情况,存储处理完一个请求后,下一个请求还在网络(1)发送。这时存储利用率显然达不到100%,这种情况下,存储利用率无法达到100%,整个系统的吞吐量以网络为准。PS:一般情况下,异步IO都是由多个线程并发处理的。

 

其实这种异步写IO的处理办法,原理很简单,用的非常广泛,存储软件写IO都采用这种方式。

 

说完异步IO,不得不提一下他的兄弟技术:预读。

 

l  预读:

 

预读的作用是优化读IO的。写IO可以不用到达存储就直接返回,预读同样可以使得读IO不用到达存储就直接返回。预读原理大致如下:通过对应用程序读IO的位置分析,预测其即将读取的位置。比如一个程序读了1、2、3这个三个位置,那么很有可能他即将读取4、5、6、7这些位置。那么客户端预读模块预先将4、5、6、7的数据取到客户端缓存,应用程序在读取4的时候,就无需将请求发送到存储端,而是直接在客户端就返回了。

 

预读,对于存储利用率来说,就很像异步IO(延迟写)的原理了。

 

预读的最大难点,是提升预读的命中率,就是说预读出来的数据,有多少是真正应用程序(用户)需要的,如果这个比率很低,则浪费了带宽资源。关于预读的算法,还是比较复杂的,需要费很多口水,也不见得说得清楚。

 

其他优化技术

除开上文说的多线程、异步IO、和预读之外还有什么办法能提升性能呢?其实还是老思路,大块IO和顺序IO。

 

对于写IO来说,在存储这端,先把写IO全部异步写到内存中,比如说1G内存为限。优化点:一是,写相同位置的合并写;二是,合并相连接的IO;三是,对IO进行排序。对于磁盘阵列来说,还需要满条带写,这是由于RAID的算法所致。

 

对于读IO来说,在存储这端,主要是针对预读的优化,原理可参考写IO的优化方式,不再赘述。

 

综合分析

在实际项目中,可以参考上述各方面。不过有时候,世事无绝对,比方说线程多可以增加存储利用率,但是线程一多,又会影响IO的顺序性。虽然存储利用率高,但是总的吞吐量反而降低了。

 

又如,使用缓存技术,不可避免的增加了内存拷贝,当缓存写满,异步效果减弱的时候,那么对于单个IO的响应时间来说,又无疑的变长了。总的来说,就是需要实际问题实际考虑,看看侧重点在哪个方面,是需要高的IOPS,还是吞吐量或者是在意单个IO的响应时间。

 

                                                                                                                                                               Todo.sobey

                                                                                                                                                               2013.12.20

猜你喜欢

转载自blog.csdn.net/s695540301/article/details/52742635
今日推荐