您的位置:首页 > 其它

大话存储-学习总结6-系统IO路径及优化

2016-10-21 00:12 288 查看

理解主机端IO路径架构

应用程序层

1. NFS下的缓存机制

默认mount参数下的IO

默认条件下使用异步(async)方式,rsize=wsize=65535。内核不会透传程序的IO给NFS Server,对于写IO会延缓执行,积累一定的时间以便合并上层的IO。不管读还是写,async方式都会具有一定的效果,尤其是连续的IO地址。

Linux下使用NFS,对于写操作,不管offset是否为Page或者512B对其,都没有任何写惩罚存在,对于读操作,也只在随机读的情况下出现了读惩罚,其他任何情况下都没有惩罚.

可以使用dd命令测试,dd是一个使用同步调用+buffered IO模式的程序.

dd if=/mnt/3 of=/dev/null bs=1500 count=100


dd为同步调用,到了底层,内核将dd的写IO数据合并,并且以异步的方式高效的发送给NFS服务器.

指定同步(sync)参数

需要了解,内核的异步过程,只对Buffered IO模式下的同步写、异步写、异步读有意义.

对于读立即执行,不一定表示不可以进行Prefetch和Cache Hit操作,但是对于写立即执行,却绝对不可以将待写的数据缓存起来延迟处理。

指定rsize/wsize参数

rsize/wsize,对于NFS的IO逻辑没有任何影响,收到影响的只是底层传输的数据包数量和大小任何情况下均不要降低rsize或者wsize,百害而无一利。

使用O_DIRECT参数

由于Linux下的NFS有很明显的预读力度。只在特定的条件下(小的随机读)有读惩罚,写惩罚一点也没有,因此很少使用DIO选项,除非应用中已经做了非常完善的缓存策略(如许多数据库就是如此).

多进程访问下的缓存一致性解决方法

Linux下的NFS缓存一致性,从严格到不严格一次为使用DIO模式、使用noac选项来mount、降低actimeo阈值到尽量低的值、默认mount参数。GETATTE是多客户端访问环境下NFS实现缓存一致性的法宝。

文件系统层

文件系统一个最大的任务就是负责在逻辑文件与底层卷或者磁盘之间做映射,并且维护和优化这些映射信息。文件系统还需要负责向上层提供文件IO访问API接口,比如打开、读、写、属性修改、裁剪、扩充、锁等文件操作。另外,还需要维护缓存,包括预读、Write Back/Write Through/Flush等操作;还需要维护数据一致性,比如Log、FSCK等机制;还需要维护文件权限、Quota等。

可以把一个文件系统逻辑上分为以下三个部分。

上部(访问接口)

中部(缓存管理、文件管理)

下部(文件映射、一致性保护、底层存储卷适配)

写命中是指写入的数据对应的地址在缓存中恰好在之前的尚未被写盘的IO数据。

卷管理层

块设备

卷管理在某种程度上是为了弥补底层存储系统的一些不足之处,比如LUN空间的动态管理等。卷管理最大的任务是做Block级的映射,对于IO处理,卷层只是做一个将映射翻译之后的IO向下转发的动作以及反向过程。

即使上层的IO不是4KB对齐,底层的IO也应该是4KB对齐的。

读惩罚

当某个读IO请求的IO Size不可被OS Page Size或者Disk Sector Size整除时,这个读请求就会产生读惩罚。但是如果边界未4K对齐,仍然可能产生读惩罚。

写惩罚

写惩罚的表现是既有额外的读操作,又有额外的写操作。比读惩罚浪费更多的资源。

字符设备

概述

传统的字符设备是转指一类接受字符流的物理终端、键盘等。这种设备可以直接对设备进行底层的操作而不使用缓存,而且每次IO必须以一个字符为单位。

卷抽象出来的字符设备只是抽象出来了字符设备所具有的特点。对字符设备进行IO操作必须遵循底层的最小单位对齐规则,比如对于卷字符设备来说,每个IO长度只能是扇区。

底层发出的IO长度与应用层发出的IO长度一一对应。

裸设备

字符设备又被称为裸设备。寓意在于可以直接对裸设备进行IO操作,只不过需要自行维护数据,如扇区映射以及预读缓存等。由于使用文件系统缓存以及内核缓存容易造成数据的不一致性且容易造成读写惩罚,对于IO性能要求高的程序,可以直接操作底层的物理设备。

Direct IO

如果即不想使用FS的缓存以防造成读写惩罚,又想利用文件系统的其他功能,则可以使用DIO模式。

这里要注意一个概念,操作系统内有很多缓存,而用户程序的第一处缓存并不是通常理解的FS缓存,而是SystemBuffer。因为每发起一个IO请求,操作系统会根据程序IO请求的空间在操作系统内存空间分配相同大小的内存用于充当SystemBuffer,然后再往下才是文件系统缓存。

设备驱动层

SCSI设备驱动链

其流程图如下



可以使用iostat工具监控IO状况。还可以使用blktrace对块级IO进行监控。

ATA设备驱动链

Linux使用一种LibATA库来负责将SCSI协议转换为ATA协议并发送给ATA控制器驱动程序。

注意

块设备由于底层IO Scheduler可能造成IO乱序重排执行情况,在发生系统宕机情况时,底层数据的一致性就无法得到保证。由于文件系统建立在块设备上,所以FSCK是一种恢复数据一致性的手段,但FSCK只能保证文件系统元数据的一致性却保证不了数据实际内容的一致性,所以,关键应用程序都直接使用完全透传程序IO请求的字符设备进行IO操作。

IO路径中Queue Depth和Queue Length

Queue Depth指的是Queue的最大长度,而Queue Length指的是Queue的当前长度。

Queue Length在一定程度上反应了当前系统的忙闲程度,监测到的Queue Length越长,就证明Queue积压越大,那么单个IO的延迟也就越高。

IO Latency = (Queue Length + 1) * IO Service Time

= (Queue Length + 1) * 其下层的IO Latency

如果IOPS尚未达到额定饱和值而Queue积压,那么说明瓶颈归于磁盘;如果IOPS饱和,说明瓶颈归于存储控制器的处理能力;如果带宽饱和,那么瓶颈归于链路本身。

time [-p] command [arguments…]

time命令可以统计命令执行的时间

Queue Length 和 IOPS的关系

IOPS = Queue Length / Average Response Time(ART)

IO Size和IO延迟的关系

IO Size越大,从盘片读写以及传输每个IO所用的时间就越长。所以,Write Merge操作其实增加了每个IO的延迟,但是它提高了效率,提高了系统的吞吐量。一些网络技术,如Infineband,其传输单元小,对于一些小的IO操作能够实现较高的响应速度,适合高实时性的传输,但是其整体的吞吐率不一定比其他传输技术高。

面向SSD的Queue优化

需要更大的Queue Depth。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  存储