谈数据,就要说说 按数据结构来组织、存储和管理数据的数据库,目前我们使用的数据库管理系统mysql为主,这也是目前使用最广泛的数据库管理系统之一。
  当数据库存储的数据量达到一定级别后,数据库瓶颈就会成为网站架构中最具挑战性的问题。
从硬件和系统层面,我们会想尽各种方法来解决数据库访问瓶颈问题,比如重新规划数据库涉及,根据不同纬度拆分数据库,数据库前端增加内存缓存系统,应用程序代码优化等。
  当软件解决方案逐渐无法解决数据库瓶颈问题的时候,我们就需要寻求硬件的解决方案。在高性能的数据库系统中,性能瓶颈逐渐主要集中在存储IO
硬件方案:加内存?SSD替换SAS HDD?加服务器?NO,天啊,老板不会同意这么干的!就算老板同意(基本上都不太可能),那能真正解决IO的瓶颈问题吗?
  刚好这两天看到同事的桌子上放着几盒高大上的PCIe SSD 存储卡(你猜下这张卡得要多少张毛爷爷?比服务器便宜):
spacer.gif
相关理论数据
用户可用容量 :
容量:3200GB,2块闪存存储卡(单卡2048G)
接口类型:Native(原生) PCIe接口(PCIe 2.0x8 Full-height half-length),两块存储卡中间的散热片下面是SSD主控制芯片。
IOPS :
读带宽: 2.0GB/s(看片想看哪里点那里)
写带宽:1.9GB/s (光纤下载,嗖搜 就下完了)
随机读取 IOPS  -4KB   500,000
随机写入 IOPS  -4KB   480,000
延迟  随机读延迟 -4KB 70us  随机写延迟 -4KB 9us
功耗:8W~25W (一个节能小灯泡)
Direct-IONative PCI-Express SSD 的性能为什么这么好?

  在解决这个疑问之前,我们可以先了解下相对于 Direct-IO  Native PCI-Express  SSD,以HDD硬盘为主流的传统存储方案。
如下图所示,机械硬盘与固态硬盘:
spacer.gif
     传统存储方案中,基于磁记录硬盘(HDD)由于受机械臂寻址读写的限制,随机读取数据时需要磁头机械定位,即使高端15K基于SAS/FC 接口的 HDD 的每秒钟完成的随机读写次数 IOPS 通常限制在 200 次左右,比较擅长顺序读写。SSD 没有了机械臂,无需耗费寻道时间,更擅长与随机读写。
     顺序读写?随机读写? 当然是随机读写更符合真实的应用场景了,所以毋庸置疑,SSD固态硬盘的读写性能要优于传统机械硬盘。

    SSD的出现为突破性能瓶颈带来了可能:伴随着SSD技术的成熟,SSD开始大规模地被采用。为了兼容已有的主板接口,很多SSD采用了与 HDD相同的接口, 如SAS(Serial Attached SCSI)或者 FC (Fiber Channel),并在物理形式上与 HDD 相似,如 2.5 英寸或 3.5 英寸。采用传统硬盘接口的SSD直接在现有的系统中取代 HDD 可以在一定的程度上缓解存储系统的瓶颈,改善系统效能。
普通的 SSD 采用模拟 HDD 的方式在兼容性上有一定的优势,但在性能上有非常大的限制:复杂的数据链路导致高 IO 延迟,SSD性能受嵌入式CPU限制,冗余的 IO 调度。
由于机械转动速度的限制,传统的单个15K转硬盘能够提供的IOPS在150-200数量级左右;SSD虽然没有了机械结构,但是由于SCSI/SAS接口界面、传输协议、软件驱动等部分的性能限制,可以提供IOPS也只能到达3000-10000数量级;而实际环境中有某些应用需要高达的10000-100000数量级的IOPS性能,因此我们需要绕过SCSI/SAS协议,对SSD实现更高效的IO访问。
 为了解决SSD性能被限制问题,于是就出现了PCI-Express SSD(特点:高吞吐,低时延的方案,使用PCI-epress 接口来提升性能。native PCIe SSD扩展卡直接连在PCIe高速通道上,卡上没有RAID控制器与SAS控制器,因此时延极小,可以充分利用SSD提供超高的IO性能。
SAS接口的SSD方案如图所示: 性能消耗在各种控制器系统总线buffer上。
spacer.gif
Direct-IO Native(原生) PCIe SSD 采用了原生 (native) PCIe的主控器,绕开了传统的SATA/SAS存储协议,并充分利用主机CPU强大的处理能力对闪存进行直接读写。
spacer.gif
PCIe SSD卡通过PCIe总线直接与CPU通信,缩短存储访问路径,再结合flash的高速读写性能,极大的提升存储性能,解决存储IO瓶颈。
PCIe SSD卡的时延性能仅次于内存
PCIe SSD的接口是一种表示形式,它可能是PCI-E传统接口,以显卡的形状出现。它的关键在于PCI-E 原生(native)/桥接(bridged)主控,这决定它是否能走PCI-E总线。
原生:PCIe to NAND flash; either FPGA or ASIC,走PC-E总线
桥接:PCIe-SAS/SATA RAID controller (RoC) + SAS/SATA SSDs
请自行脑补:内存(集显)----PCIE 显卡内存-------PCIE SSD存储
有一个概念,有兴趣的同学可自行查询:
NVM Express(简称NVMe)是一个针对PCIe SSD的主机控制芯片接口标准,规范SSD控制器与操作系统之间的通信连接。
Direct-IO  又是什么东东呢,为什么可以提升数据读写性能?

标准IO(缓存 I/O):

图 1. 以标准的方式对文件进行读写
   普通的I/O操作一般会被内核缓存,这种 I/O被称作缓存 I/O(Buffered I/O)。文件访问不经过操作系统内核的缓存,数据直接在磁盘和应用程序地址空间进行传输,所以该文件访问的机制称作为直接 I/O。
在 Linux 的缓存 I/O 机制中,操作系统会将 I/O 的数据缓存在文件系统的页缓存( page cache )中,也就是说,数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。缓存 I/O 有以下这些优点:缓存 I/O 使用了操作系统内核缓冲区,在一定程度上分离了应用程序空间和实际的物理设备。缓存 I/O 可以减少读盘的次数,从而提高性能。Linux中就提供了这样一种文件访问机制,对于将 I/O 缓存存放在用户地址空间的应用程序来说,直接 I/O 是一种非常高效的手段。
   在缓存 I/O 机制中,DMA 方式可以将数据直接从磁盘读到页缓存中,或者将数据从页缓存直接写回到磁盘上,而不能直接在应用程序地址空间和磁盘之间进行数据传输,这样的话,数据在传输过程中需要在应用程序地址空间和页缓存之间进行多次数据拷贝操作,这些数据拷贝操作所带来的 CPU 以及内存开销是非常大的。对于某些特殊的应用程序来说,避开操作系统内核缓冲区而直接在应用程序地址空间和磁盘之间传输数据会比使用操作系统内核缓冲区获取更好的性能。
   对于某些应用程序来说,它会有它自己的数据缓存机制,比如,它会将数据缓存在应用程序地址空间,这类应用程序完全不需要使用操作系统内核中的高速缓冲存储器,这类应用程序就被称作是自缓存应用程序( self-caching applications )。数据库管理系统是自缓存应用程序的一个代表。自缓存应用程序倾向于使用数据的逻辑表达方式,而非物理表达方式;当系统内存较低的时候,自缓存应用程序会让这种数据的逻辑缓存被换出,而并非是磁盘上实际的数据被换出。自缓存应用程序对要操作的数据的语义了如指掌,所以它可以采用更加高效的缓存替换算法。自缓存应用程序有可能会在多台主机之间共享一块内存,那么自缓存应用程序就需要提供一种能够有效地将用户地址空间的缓存数据置为无效的机制,从而确保应用程序地址空间缓存数据的一致性。
      对于自缓存应用程序来说,缓存 I/O 明显不是一个好的选择。Linux 中的直接 I/O 技术非常适用于自缓存这类应用程序,该技术省略掉缓存 I/O 技术中操作系统内核缓冲区的使用,数据直接在应用程序地址空间和磁盘之间进行传输,从而使得自缓存应用程序可以省略掉复杂的系统级别的缓存结构,而执行程序自己定义的数据读写管理,从而降低系统级别的管理对应用程序访问数据的影响。
 Direct-IO: 区别于缓冲读写(Buffered I/O),Direct-IO的目的在于绕过文件系统的cache,直接对block设备上的文件进行读写(I/O请求被从文件系统块直接映射到设备块.),
其目的在于提高读写性能(以读为例,少了一次从文件系统缓冲区到用户态buffer的拷贝过程),理论上文件仅读/写一次的情况下应该是比较比默认的读/写方式效率高,针对数据库存在自己管理文件cache。
文件系统缓冲区:当系统读写块设备,为了加快读写速度,系统维护了一个块缓冲区。当系统读数据的时候,先去缓冲区中读,如果没有,再读写磁盘。当系统写数据的时候,先写数据到缓冲区中。
数据库本身已经有自己的数据缓冲区,再加上系统文件的缓冲区,数据就被缓存了两次,系统的内存就被浪费了。如果数据库的块比系统文件的块小,那么就会造成系统的浪费。

     凡是通过直接 I/O 方式进行数据传输,数据均直接在用户地址空间的缓冲区和磁盘之间直接进行传输,完全不需要页缓存的支持。操作系统层提供的缓存往往会使应用程序在读写数据的时候获得更好的性能,但是对于某些特殊的应用程序,比如说数据库管理系统这类应用,他们更倾向于选择他们自己的缓存机制,因为数据库管理系统往往比操作系统更了解数据库中存放的数据,数据库管理系统可以提供一种更加有效的缓存机制来提高数据库中数据的存取性能。


Direct-IO方式:
图 4. 数据传输不经过操作系统内核缓冲区

直接 I/O 的优点:干掉了数据复制,减少了cpu和内存的使用,提升了自缓存系统的数据交互和组织优势。

直接 I/O 最主要的优点就是通过减少操作系统内核缓冲区和应用程序地址空间的数据拷贝次数,降低了对文件读取和写入时所带来的 CPU 的使用以及内存带宽的占用。这对于某些特殊的应用程序,比如自缓存应用程序来说,不失为一种好的选择。如果要传输的数据量很大,使用直接 I/O 的方式进行数据传输,而不需要操作系统内核地址空间拷贝数据操作的参与,这将会大大提高性能。

直接 I/O 潜在可能存在的问题

直接 I/O 并不一定总能提供令人满意的性能上的飞跃。设置直接 I/O 的开销非常大,而直接 I/O 又不能提供缓存 I/O 的优势。缓存 I/O 的读操作可以从高速缓冲存储器中获取数据,而直接 I/O 的读数据操作会造成磁盘的同步读,这会带来性能上的差异 , 并且导致进程需要较长的时间才能执行完;对于写数据操作来说,使用直接 I/O 需要 write() 系统调用同步执行,否则应用程序将会不知道什么时候才能够再次使用它的 I/O 缓冲区。与直接 I/O 读操作类似的是,直接 I/O 写操作也会导致应用程序关闭缓慢。所以,应用程序使用直接 I/O 进行数据传输的时候通常会和使用异步 I/O 结合使用。

Linux 中的直接 I/O 访问文件方式可以减少 CPU 的使用率以及内存带宽的占用,但是直接 I/O 有时候也会对性能产生负面影响。所以在使用直接 I/O 之前一定要对应用程序有一个很清醒的认识,只有在确定了设置缓冲 I/O 的开销非常巨大的情况下,才考虑使用直接 I/O。
参考文档:
http://www.shannon-sys.com/database_solution_zh.html