赞
踩
IO 性能对于一个系统的影响是至关重要的。一个系统经过多项优化以后,瓶颈往往落在数据库;而数据库经过多种优化以后,瓶颈最终会落到 IO 。而 IO 性能的发展,明显落后于 CPU 的发展。 Memchached 也好, NoSql 也好,这些流行技术的背后都在直接或者间接地回避 IO 瓶颈,从而提高系统性能。
IO 系统的分层:
上图层次比较多,但总的就是三部分。磁盘 (存储)、 VM (卷管理)和文件系统 。专有名词不好理解,打个比方说:磁盘就相当于一块待用的空地; LVM 相当于空地上的围墙(把空地划分成多个部分);文件系统则相当于每块空地上建的楼房(决定了有多少房间、房屋编号如何,能容纳多少人住);而房子里面住的人,则相当于系统里面存的数据。
对应了上图的 File System 和 Buffer Cache 。
File System (文件系统):解决了空间管理的问题 ,即:数据如何存放、读取。
Buffer Cache :解决数据缓冲的问题。对读,进行 cache ,即:缓存经常要用到的数据;对写,进行 buffer ,缓冲一定数据以后,一次性进行写入。
对应上图的 Vol Mgmt 。
VM 其实跟 IO 没有必然联系。他是处于文件系统和磁盘(存储)中间的一层。 VM 屏蔽了底层磁盘对上层文件系统的影响 。当没有 VM 的时候,文件系统直接使用存储上的地址空间,因此文件系统直接受限于物理硬盘,这时如果发生磁盘空间不足的情况,对应用而言将是一场噩梦,不得不新增硬盘,然后重新进行数据复制。而 VM 则可以实现动态扩展,而对文件系统没有影响。另外, VM 也可以把多个磁盘合并成一个磁盘,对文件系统呈现统一的地址空间,这个特性的杀伤力不言而喻。
对应上图的 Device Driver 、 IO Channel 和 Disk Device
数据最终会放在这里,因此,效率、数据安全、容灾是这里需要考虑的问题。而提高存储的性能,则可以直接提高物理 IO 的性能
2. Logical IO vs Physical IO
逻辑 IO 是操作系统发起的 IO ,这个数据可能会放在磁盘上,也可能会放在内存(文件系统的 Cache )里。
物理 IO 是设备驱动发起的 IO ,这个数据最终会落在磁盘上。
逻辑 IO 和物理 IO 不是一一对应的。
这部分的东西在网络编程经常能看到,不过在所有 IO 处理中都是类似的。
IO 请求的两个阶段 :
等待资源阶段 : IO 请求一般需要请求特殊的资源(如磁盘、 RAM 、文件),当资源被上一个使用者使用没有被释放时, IO 请求就会被阻塞,直到能够使用这个资源。
使用资源阶段 :真正进行数据接收和发生。
举例说就是排队 和服务。
在等待数据 阶段, IO 分为阻塞 IO 和非阻塞 IO 。
阻塞 IO :资源不可用时, IO 请求一直阻塞,直到反馈结果(有数据或超时)。
非阻塞 IO :资源不可用时, IO 请求离开返回,返回数据标识资源不可用
在使用资源 阶段, IO 分为同步 IO 和异步 IO 。
同步 IO :应用阻塞在发送或接收数据的状态,直到数据成功传输或返回失败。
异步 IO :应用发送或接收数据后立刻返回,数据写入 OS 缓存,由 OS 完成数据发送或接收,并返回成功或失败的信息给应用。
按照 Unix 的 5 个 IO 模型划分
从性能上看,异步 IO 的性能无疑是最好的。
各种 IO 的特点
最重要的三个指标
IOPS
IOPS ,即每秒钟处理的 IO 请求数量。 IOPS 是随机访问类型业务( OLTP 类 )很重要的一个参考指标。
从磁盘上进行数据读取时,比较重要的几个时间是:寻址时间 (找到数据块的起始位置),旋转时间 (等待磁盘旋转到数据块的起始位置),传输时间 (读取数据的时间和返回的时间)。其中寻址时间是固定的(磁头定位到数据的存储的扇区即可),旋转时间受磁盘转速的影响,传输时间受数据量大小的影响和接口类型的影响(不用硬盘接口速度不同),但是在随机访问类业务中,他的时间也很少。因此,在硬盘接口相同的情况下, IOPS 主要受限于寻址时间和传输时间。以一个 15K 的硬盘为例,寻址时间固定为 4ms ,传输时间为 60s/15000*1/2=2ms ,忽略传输时间。 1000ms/6ms=167 个 IOPS 。
在没有文件系统、没有 VM (卷管理)、没有 RAID 、没有存储设备的情况下,这个答案还是成立的。但是当这么多中间层加进去以后,这个答案就不是这样了。物理硬盘提供的 IO 是有限的,也是整个 IO 系统存在瓶颈的最大根源。所以,如果一块硬盘不能提供,那么多块在一起并行处理,这不就行了吗?确实是这样的。可以看到,越是高端的存储设备的 cache 越大,硬盘越多,一方面通过cache 异步处理IO ,另一方面通过盘数增加,尽可能把一个OS 的IO 分布到不同硬盘上,从而提高性能 。文件系统则是在 cache 上会影响,而 VM 则可能是一个 IO 分布到多个不同设备上( Striping )。
所以,一个 OS 的IO 在经过多个中间层以后,发生在物理磁盘上的IO 是不确定的。可能是一对一个,也可能一个对应多个 。
对单块磁盘的 IOPS 的计算没有没问题,但是当系统后面接的是一个存储系统时、考虑不同读写比例, IOPS 则很难计算,而需要根据实际情况进行测试。主要的因素有:
当时上面 N 多因素混合在一起以后, IOPS 的值就变得扑朔迷离了。所以,一般需要通过实际应用的测试才能获得。
IO Response Time
即 IO 的响应时间。 IO 响应时间是从操作系统内核发出一个 IO 请求到接收到 IO 响应的时间。因此, IO Response time 除了包括磁盘获取数据的时间,还包括了操作系统以及在存储系统内部 IO 等待的时间。一般看,随 IOPS 增加,因为 IO 出现等待, IO 响应时间也会随之增加。对一个 OLTP 系统, 10ms 以内的响应时间,是比较合理的。下面是一些 IO 性能示例:
需要注意, IOPS 与 IO Response Time 有着密切的联系。一般情况下, IOPS 增加,说明 IO 请求多了, IO Response Time 会相应增加。但是会出现 IOPS 一直增加,但是 IO Response Time 变得非常慢,超过 20ms 甚至几十 ms ,这时候的 IOPS 虽然还在提高,但是意义已经不大,因为整个 IO 系统的服务时间已经不可取。
Throughput
为吞吐量。这个指标衡量标识了最大的数据传输量。如上说明,这个值在顺序访问或者大数据量访问的情况下会比较重要 。尤其在大数据量写的时候。
吞吐量不像 IOPS 影响因素很多,吞吐量一般受限于一些比较固定的因素,如:网络带宽、 IO 传输接口的带宽、硬盘接口带宽等。一般他的值就等于上面几个地方中某一个的瓶颈。
一些概念
IO Chunk Size
即单个 IO 操作请求数据的大小。一次 IO 操作是指从发出 IO 请求到返回数据的过程。 IO Chunk Size 与应用或业务逻辑有着很密切的关系。比如像 Oracle 一类数据库,由于其 block size 一般为 8K ,读取、写入时都此为单位,因此, 8K 为这个系统主要的 IO Chunk Size 。 IO Chunk Size
小,考验的是 IO 系统的 IOPS 能力; IO Chunk Size 大,考验的时候 IO 系统的 IO 吞吐量。
Queue Deep
熟悉数据库的人都知道, SQL 是可以批量提交的,这样可以大大提高操作效率。 IO 请求也是一样, IO 请求可以积累一定数据,然后一次提交到存储系统,这样一些相邻的数据块操作可以进行合并,减少物理 IO 数。而且 Queue Deep 如其名,就是设置一起提交的 IO 请求数量的。一般 Queue Deep 在 IO 驱动层面上进行配置。
Queue Deep 与 IOPS 有着密切关系。 Queue Deep 主要考虑批量提交 IO 请求,自然只有 IOPS 是瓶颈的时候才会有意义,如果 IO 都是大 IO ,磁盘已经成瓶颈, Queue Deep 意义也就不大了。一般来说, IOPS 的峰值会随着 Queue Deep 的增加而增加 ( 不会非常显著 ) , Queue Deep 一般小于 256 。
随机访问(随机IO )、顺序访问(顺序IO )
随机访问的特点是每次 IO 请求的数据在磁盘上的位置跨度很大 (如:分布在不同的扇区),因此 N个 非常小的 IO 请求(如: 1K ),必须以 N 次 IO 请求才能获取到相应的数据。
顺序访问的特点跟随机访问相反,它请求的数据在磁盘的位置是连续的 。当系统发起 N个 非常小的 IO 请求(如: 1K )时,因为一次 IO 是有代价的,系统会取完整的一块数据(如 4K 、 8K ),所以当第一次 IO 完成时,后续 IO 请求的数据可能已经有了。这样可以减少 IO 请求的次数。这也就是所谓的预取。
随机访问和顺序访问同样是有应用决定的。如数据库、小文件的存储的业务,大多是随机 IO 。而视频类业务、大文件存取,则大多为顺序 IO 。
选取合理的观察指标:
以上各指标中,不用的应用场景需要观察不同的指标,因为应用场景不同,有些指标甚至是没有意义的。
随机访问和IOPS : 在随机访问场景下, IOPS 往往会到达瓶颈,而这个时候去观察 Throughput ,则往往远低于理论值。
顺序访问和Throughput :在顺序访问的场景下, Throughput 往往会达到瓶颈(磁盘限制或者带宽),而这时候去观察 IOPS ,往往很小。
文件系统各有不同,其最主要的目标就是解决磁盘空间的管理问题,同时提供高效性、安全性。如果在分布式环境下,则有相应的分布式文件系统。 Linux 上有 ext 系列, Windows 上有 Fat 和 NTFS 。如图为一个 linux 下文件系统的结构。
其中 VFS ( Virtual File System )是 Linux Kernel 文件系统的一个模块,简单看就是一个 Adapter ,对下屏蔽了下层不同文件系统之间的差异,对上为操作系统提供了统一的接口 .
中间部分为各个不同文件系统的实现。
再往下是 Buffer Cache 和 Driver 。
文件系统的结构
各种文件系统实现方式不同,因此性能、管理性、可靠性等也有所不同。下面为 Linux Ext2 ( Ext3 )的一个大致文件系统的结构。
Boot Block 存放了引导程序。
Super Block 存放了整个文件系统的一些全局参数,如:卷名、状态、块大小、块总数。他在文件系统被 mount 时读入内存,在 umount 时被释放。
上图描述了 Ext2 文件系统中很重要的三个数据结构和他们之间的关系。
Inode : Inode 是文件系统中最重要的一个结构。如图,他里面记录了文件相关的所有信息,也就是我们常说的 meta 信息。包括:文件类型、权限、所有者、大小、 atime 等。 Inode 里面也保存了指向实际文件内容信息的索引。其中这种索引分几类:
如图:
Directory 代表了文件系统中的目录,包括了当前目录中的所有 Inode 信息。其中每行只有两个信息,一个是文件名,一个是其对应的 Inode 。需要注意, Directory 不是文件系统中的一个特殊结构,他实际上也是一个文件,有自己的 Inode ,而它的文件内容信息里面,包括了上面看到的那些文件名和 Inode 的对应关系。如下图:
Data Block 即存放文件的时间内容块。 Data Block 大小必须为磁盘的数据块大小的整数倍,磁盘一般为 512 字节,因此 Data Block 一般为 1K 、 2K 、 4K 。
Buffer Cache
Buffer & Cache
虽然 Buffer 和 Cache 放在一起了,但是在实际过程中 Buffer 和 Cache 是完全不同了。 Buffer 一般对于写而言,也叫“缓冲区”,缓冲使得多个小的数据块能够合并成一个大数据块,一次性写入; Cache 一般对于读而且,也叫“缓存”,避免频繁的磁盘读取。如图为 Linux 的 free 命令,其中也是把 Buffer 和 Cache 进行区分,这两部分都算在了 free 的内存。
Buffer Cache
Buffer Cache 中的缓存,本质与所有的缓存都是一样,数据结构也是类似,下图为 VxSF 的一个 Buffer Cache 结构。
这个数据结构与 memcached 和 Oracle SGA 的 buffer 何等相似。左侧的 hash chain 完成数据块的寻址,上方的的链表记录了数据块的状态。
Buffer vs Direct I/O
文件系统的 Buffer 和 Cache 在某些情况下确实提高了速度,但是反之也会带来一些负面影响。一方面文件系统增加了一个中间层,另外一方面,当 Cache 使用不当、配置不好或者有些业务无法获取 cache 带来的好处时, cache 则成为了一种负担。
适合 Cache 的业务:串行的大数据量业务,如: NFS 、 FTP 。
不适合 Cache 的业务:随机 IO 的业务。如: Oracle ,小文件读取。
块设备、字符设备、裸设备
这几个东西看得很晕,找了一些资料也没有找到很准确的说明。
从硬件设备的角度来看,
从操作系统的角度看(对应操作系统的设备文件类型的 b 和 c ),
# ls -l /dev/*lv
brw------- 1 root system 22, 2 May 15 2007 lv
crw------- 2 root system 22, 2 May 15 2007 rlv
如上,相比之下,字符设备在使用更为直接,而块设备更为灵活。文件系统一般建立在块设备上,而为了追求高性能,使用字符设备则是更好的选择,如 Oracle 的裸设备使用。
裸设备
裸设备也叫裸分区,就是没有经过格式化、没有文件系统的一块存储空间。可以写入二进制内容,但是内容的格式、其中信息的组织等问题,需要使用它的人来完成。文件系统就是建立在裸设备之上,并完成裸设备空间的管理。
CIO
CIO 即并行 IO ( Concurrent IO )。在文件系统中,当某个文件被多个进程同时访问时,就出现了 Inode 竞争的问题。一般地,读操作使用的共享锁,即:多个读操作可以并发进行,而写操作使用排他锁。当锁被写进程占用时,其他所有操作均阻塞。因此,当这样的情况出现时,整个应用的性能将会大大降低。如图:
CIO 就是为了解决这个问题。而且 CIO 带来的性能提高直逼裸设备。当文件系统支持 CIO 并开启 CIO 时, CIO 默认会开启文件系统的 Direct IO ,即:让 IO 操作不经过 Buffer 直接进行底层数据操作。由于不经过数据 Buffer ,在文件系统层面就无需考虑数据一致性的问题,因此,读写操作可以并行执行。
在最终进行数据存储的时候,所有操作都会串行执行, CIO 把这个事情交个了底层的 driver 。
LVM(逻辑卷管理),位于操作系统和硬盘之间,LVM屏蔽了底层硬盘带来的复杂性。最简单的,LVM使得N块硬盘在OS看来成为一块硬盘,大大提高了系统可用性。
LVM 的引入,使得文件系统和底层磁盘之间的关系变得更为灵活,而且更方便关系。 LVM 有以下特点:
LVM 可以做动态磁盘扩展,想想看,当系统管理员发现应用空间不足时,敲两个命令就完成空间扩展,估计做梦都要笑醒:)
LVM 中有几个很重要的概念:
LV (logical volume ) :逻辑卷。 LV 是最终可供使用卷, LV 在 VG 中创建,有了 VG , LV 创建是只需考虑空间大小等问题,对 LV 而言,他看到的是一直联系的地址空间,不用考虑多块硬盘的问题。
有了上面三个, LVM 把单个的磁盘抽象成了一组连续的、可随意分配的地址空间。除上面三个概念外,还有一些其他概念:
对于上面几个概念,无需刻意去记住,当你需要做这么一个东西时,这些概念是自然而然的。PV把物理硬盘 转换成LVM中对于的逻辑(解决如何管理物理硬盘的问题),VG是PV的集合(解决如何组合PV的问题),LV是VG上空间的再划分(解决如何给OS使用 空间的问题);而PE、LE则是空间分配时的单位。
如图,为两块 18G 的磁盘组成了一个 36G 的 VG 。此 VG 上划分了 3 个 LV 。其 PE 和 LE 都为 4M 。其中 LV1 只用到了 sda 的空间,而 LV2 和 LV3 使用到了两块磁盘。
串联( Concatenation ): 按顺序使用磁盘,一个磁盘使用完以后使用后续的磁盘。
条带化( Striping ): 交替使用不同磁盘的空间。条带化使得 IO 操作可以并行,因此是提高 IO 性能的关键。另外, Striping 也是 RAID 的基础。如: VG 有 2 个 PV , LV 做了条带数量为 2 的条带化,条带大小为 8K ,那么当 OS 发起一个 16K 的写操作时,那么刚好这 2 个 PV 对应的磁盘可以对整个写入操作进行并行写入。
Striping 带来的问题:
镜像( mirror )
如同名字。 LVM 提供 LV 镜像的功能。即当一个 LV 进行 IO 操作时,相同的操作发生在另外一个 LV 上。这样的功能为数据的安全性提供了支持。如图,一份数据被同时写入两个不同的 PV 。
使用 mirror 时,可以获得一些好处:
快照(Snapshot)
快照如其名,他保存了某一时间点磁盘的状态,而后续数据的变化不会影响快照,因此,快照是一种备份很好手段。
但是快照由于保存了某一时间点数据的状态,因此在数据变化时,这部分数据需要写到其他地方,随着而来回带来一些问题。关于这块,后续存储也涉及到类似的问题,后面再说。
这部分值得一说的是多路径问题。 IO 部分的高可用性在整个应用系统中可以说是最关键的,应用层可以坏掉一两台机器没有问题,但是如果 IO 不通了,整个系统都没法使用。如图为一个典型的 SAN 网络,从主机到磁盘,所有路径上都提供了冗余,以备发生通路中断的情况。
如上图结构,由于存在两条路径,对于存储划分的一个空间,在 OS 端会看到两个(两块磁盘或者两个 lun )。可怕的是, OS 并不知道这两个东西对应的其实是一块空间,如果路径再多,则 OS 会看到更多。还是那句经典的话,“计算机中碰到的问题,往往可以通过增加的一个中间层来解决”,于是有了多路径软件。他提供了以下特性:
Fail over 的能力一般 OS 也可能支持,而 load balance 则需要与存储配合,所以需要根据存储不同配置安装不同的多通路软件。
多路径除了解决了高可用性,同时,多条路径也可以同时工作,提高系统性能。
Raid 很基础,但是在存储系统中占据非常重要的地位,所有涉及存储的书籍都会提到 RAID 。 RAID 通过磁盘冗余的方式提高了可用性和可高性,一方面增加了数据读写速度,另一方面增加了数据的安全性。
RAID 0
对数据进行条带化。使用两个磁盘交替存放连续数据。因此可以实现并发读写,但带来的问题是如果一个磁盘损坏,另外一个磁盘的数据将失去意义。 RAID 0 最少需要 2 块盘。
RAID 1
对数据进行镜像。数据写入时,相同的数据同时写入两块盘。因此两个盘的数据完全一致,如果一块盘损坏,另外一块盘可以顶替使用, RAID 1 带来了很好的可靠性。同时读的时候,数据可以从两个盘上进行读取。但是 RAID 1 带来的问题就是空间的浪费。两块盘只提供了一块盘的空间。 RAID 1 最少需要 2 块盘。
RAID 5 和 RAID 4
使用多余的一块校验盘。数据写入时, RAID 5 需要对数据进行计算,以便得出校验位。因此,在写性能上 RAID 5 会有损失。但是 RAID 5 兼顾了性能和安全性。当有一块磁盘损坏时, RAID 5 可以通过其他盘上的数据对其进行恢复。
如图可以看出,右下角为 p 的就是校验数据。可以看到 RAID 5 的校验数据依次分布在不同的盘上,这样可以避免出现热点盘(因为所有写操作和更新操作都需要修改校验信息,如果校验都在一个盘做,会导致这个盘成为写瓶颈,从而拖累整体性能, RAID 4 的问题)。 RAID 5 最少需要 3 块盘。
RAID 6
RAID 6 与 RAID 5 类似。但是提供了两块校验盘(下图右下角为 p 和 q 的)。安全性更高,写性能更差了。 RAID 0 最少需要 4 块盘。
RAID 10 (Striped mirror )
RAID 10 是 RAID 0 和 RAID 1 的结合,同时兼顾了二者的特点,提供了高性能,但是同时空间使用也是最大。 RAID 10 最少需要 4 块盘。
需要注意,使用 RAID 10 来称呼其实很容易产生混淆,因为 RAID 0+1 和 RAID 10 基本上只是两个数字交换了一下位置,但是对 RAID 来说就是两个不同的组成。因此,更容易理解的方式是“ Striped mirrors ”,即:条带化后的镜像—— RAID 10 ;或者“ mirrored stripes ”,即:镜像后的条带化。比较 RAID 10 和 RAID 0+1 ,虽然最终都是用到了 4 块盘,但是在数据组织上有所不同,从而带来问题。 RAID 10 在可用性上是要高于 RAID 0+1 的:
DAS 、 SAN 和 NAS
为了满足人们不断扩大的需求,存储方案也是在发展的。而 DAS 、 SAN 、 NAS 直接反映这种反映了这种趋势。
如图,对 NAS 、 SAN 、 DAS 的组成协议进行了划分,从这里也能很清晰的看出他们之间的差别。
NAS :涉及 SMB 协议、 NFS 协议,都是网络文件系统的协议。
SAN :有 FC 、 iSCSI 、 AOE ,都是网络数据传输协议。
DAS :有 PATA 、 SATA 、 SAS 等,主要是磁盘数据传输协议。
从 DAS 到 SAN ,在到 NAS ,在不同层面对存储方案进行的补充,也可以看到一种从低级到高级的发展趋势。而现在我们常看到一些分布式文件系统(如 hadoop 等)、数据库的 sharding 等,从存储的角度来说,则是在 OS 层面(应用)对数据进行存储。从这也能看到一种技术发展的趋势。
跑在以太网上的 SAN
SAN 网络并不是只能使用光纤和光纤协议,当初之所以使用 FC ,传输效率是一个很大的问题,但是以太网发展到今天被不断的完善、加强,带宽的问题也被不断的解决。因此,以太网上的 SAN 或许会成为一个趋势。
如图两个 FC 的 SAN 网络,通过 FCIP 实现了两个 SAN 网络数据在 IP 网络上的传输。这个时候 SAN 网络还是以 FC 协议为基础,还是使用光纤。
通过 iFCP 方式, SAN 网络由 FC 的 SAN 网络演变为 IP SAN 网络,整个 SAN 网络都基于了 IP 方式。但是主机和存储直接使用的还是 FC 协议。只是在接入 SAN 网络的时候通过 iFCP 进行了转换
iSCSI 是比较主流的 IP SAN 的提供方式,而且其效率也得到了认可。
对于 iSCSI ,最重要的一点就是 SCSI 协议。 SCSI ( Small Computer Systems Interface )协议是计算机内部的一个通用协议。 是一组标准集,它定义了与大量设备(主要是与存储相关的设备)通信所需的接口和协议。如图, SCSI 为 block device drivers 之下。
从 SCIS 的分层来看,共分三层:
高层:提供了与 OS 各种设备之间的接口,实现把 OS 如: Linux 的 VFS 请求转换为 SCSI 请求
中间层:实现高层和底层之间的转换,类似一个协议网关。
底层:完成于具体物理设备之间的交互,实现真正的数据处理。
参考资料:
《计算机系统结构--量化研究方法》Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。