关于SSD

企业SSD市场按照接口协议主要分为SATA SSD,PCIe SSD和NVMe SSD,其中SATA SSD沿用了传统的HDD使用的SATA协议,在企业应用和服务器兼容性上具有优势; PCIe SSD则一般使用私有协议,处于比较小众的产品;NVMe SSD则在PCIe接口上使用新的标准协议NVMe,由于NVMe由大厂Intel推出并交由nvmexpress组织推广,现在被全球大部分存储企业采纳,如memblaze,huawei,samsung都推出了相关的产品。


  1. SSD工作原理

    SSD主要由SSD控制器,FLASH存储阵列,如下图:
    1.png
    SSD主控通过若干个通道(channel)并行操作多块FLASH颗粒,类似RAID0,可以提高底层的带宽。假设主控与FLASH颗粒之间有8个通道,每个通道上挂载了一个闪存颗粒,HOST与FLASH之间数据传输速率为200MB/s。该闪存颗粒Page大小为8KB,FLASH page的读取时间为Tr=50us,平均写入时间为Tp=800us,8KB数据传输时间为Tx=40us。那么底层读取最大带宽为(8KB/(50us+40us))8 = 711MB/s,写入最大带宽为(8KB/(800us+40us))8 = 76MB/s。从上可以看出,要提高底层带宽,可以增加底层并行的颗粒数目,也可以选择速度快的FLASH颗粒(或者让速度慢的颗粒变快,比如MLC配成SLC使用)。

  2. NVMe Command

    NVMe Host(Server)和NVMe Controller(SSD)都是通过NVMe Command进行信息交互。NVMe Spec中定义了NVMe Command的格式,可以看到,NVMe Command占用64字节。其中Command的前4个字节规定如下。Command Identifier作为识别这个Command的标志,Opcode通常包含Command类型(如读写,identify等)。
    NVMe Command分为Admin Command和IO Command两大类,前者主要是用于配置,后者用于数据传输。

  3. Nvme与普通盘差异

    Nmve ssd与SATA SSD差异:
    2.png
    nmve ssd与SATA SSD的IO栈差异:
    3.png

  4. 关于性能抖动

    SSD具有很高的IO性能,但是性能稳定性不如磁盘。
    SSD性能发生变化的一个重要因素是内部GC(垃圾回收)机制的影响。
    GC会导致SSD性能发生变化,NAND Flash上的数据布局方式会对GC性能造成影响,其本质问题是数据迁移与用户IO之间的资源竞争。
    SSD性能不稳定的因素:
     NAND介质本身的Bit Error;
     读与写、擦除的冲突;
     Read Disturb、GC等问题导致性能变差。
    从外在表现来看,Bit Error的增多会导致SSD在使用过程中出现性能抖动问题,尤其是随着使用寿命的耗尽,SSD性能会发生明显的变化。另外在不同的IO 模式下,性能也不尽相同,有些SSD甚至会存在写后读的问题,紧随写之后读延迟会变得很大,达到毫秒级,这是内部IO冲突导致的。另外在同一区域大量读之后,也可能发现性能会出现抖动,这也是由于内部的Read Disturb机制开始工作了,会与用户IO发生竞争,从而导致性能抖动,甚至下降。
    当读请求和擦除请求落在了同一个通道的相同Die上,那么读请求将会由于擦除操作而被迫等待。NAND Flash的擦除操作基本上在2ms以上,如果发生这种冲突,那么IO的延迟将会从100us提升到2ms以上,从而发生严重的延迟。为解决这个问题,现在有些NAND也会提供Erase Suspend的功能,通过该命令让擦除操作暂停,让读操作先进行,从而降低读延迟。
    NAND Flash存在Read Disturb的问题,当NANDFlash一个区域被重复读之后,其Bit Error将会上升。为了解决该问题,SSD内部的Firmware会进行Read Disturb的处理。一个区域被重复读取之后,会进行数据搬移操作,该操作过程类似于Garbage Collection过程。一旦该过程被触发之后,SSD内部的IO请求数量将会上升,从而对读请求造成一定的影响,导致性能降低及抖动。

  5. GC

    机械硬盘中文件系统可以直接将新数据写入到旧数据存储的位置,可以直接覆盖旧数据。在固态硬盘中,如果想让存储无用数据的块写入新数据,就需要先把整个块删除,才可以写入新的数据
    固态硬盘并不具备直接覆盖旧数据的能力。固态硬盘GC(垃圾回收)是指把现存数据重新转移到其他闪存位置,并且把一些无用的数据彻底删除的过程。
    SSD盘中数据写入的方式,以页面为单位写入,删除数据以块为单位。要删除无用的数据,先需要把一个块内包含有用的数据先复制粘贴到全新块中的页面内,这样原来块中包含的无用数据才能够以块为单位删除。删除后,才能够写入新的数据,在擦除之前是无法写入新数据的。

  6. 写放大

    SSD写放大问题,当写入新数据时,如果SSD控制器找不到可以写入的page时,会执行GC过程,然后GC机制会将一些block中的有效数据合并写入其他的block中,然后将这些block的无效数据擦出,再将新数据写入到这些block中,而在整个过程中除了要写入用户的数据之外,实际上SSD还写入了一些其他block合并过来的数据,所以这就叫写入放大。

  7. Trim指令

    Trim指令也叫disable delete notify(禁用删除通知),是微软联合各大SSD厂商所开发的一项技术,属于ATA8-ACS规范的技术指令。
    TRIM(或者DISCARD)的出现主要为了提高SSD垃圾资源的回收效率以及减少写入放大的发生。SD而言TRIM的最大作用是清空待删除的无效数据,在SSD执行读、擦、写步骤的时候,预先把擦除的步骤先做了,这样才能发挥出SSD的性能,通常SSD掉速很大一部分原因就是待删除的无效数据太多,每次写入的时候主控都要先做清空处理,所以性能受到了限制。
    在文件系统上删除某个文件时候,简单的在逻辑数据表内把存储要删除的数据的位置标记为可用而已,而并不是真正将磁盘上的数据给删除掉。使用机械硬盘的系统根本就不需要向存储设备发送任何有关文件删除的消息,系统可以随时把新数据直接覆盖到无用的数据上。
    固态硬盘只有当系统准备把新数据要写入那个位置的时候,固态硬盘才意识到原来这写数据已经被删除。而如果在这之前,SSD执行了GC操作,那么GC会把这些实际上已经删除了的数据还当作是有效数据进行迁移写入到其他的block中,这是没有必要的。
    在没有Trim的情况下,SSD无法事先知道那些被‘删除’的数据页已经是‘无效’的,必须到系统要求在相同的地方写入数据时才知道那些数据可以被擦除,这样就无法在最适当的时机做出最好的优化,既影响GC的效率(间接影响性能),又影响SSD的寿命。

  8. SSD的个性

    全盘顺序写之后的顺序写性能会比较高,但是在全盘随机写之后的顺序写性能会略差。原因在于NAND上的数据布局初始条件的不同,GC行为会发生差异,从而导致后面的业务IO性能发生变化。
    对于SSD性能可以测试一下SSD使用率达到80%以上时SSD的性能。

  9. IO瓶颈定位工具blktrace

    关于blktrace, Blktrace是一个用户态的工具,用来收集磁盘IO信息中当IO进行到块设备层(block层,所以叫blk trace)时的详细信息(如IO请求提交,入队,合并,完成等等一些列的信息).
    blktrace是一个针对linux内核中块设备I/O层的跟踪工具,是由Linux内核块设备层的维护者开发的,目前已经集成到内核2.6.17及其之后的内核版本中。通过使用这个工具,使用者可以获取I/O请求队列的各种详细的情况,包括进行读写的进程名称、进程号、执行时间、读写的物理块号、块大小等等,是一个Linux下分析I/O相关内容的很好的工具
    能记录I/O所经历的各个步骤,从中可以分析是IO Scheduler慢还是硬件响应慢。
    使用blktrace需要挂载debugfs
    mount -t debugfs debugfs /sys/kernel/debug
    blktrace -d /dev/nvme0n1 -o test1
    文件里面存的是二进制数据,需要blkparse来解析
    或者直接:
    blktrace -d /dev/nvme0n1 -o - | blkparse -i -
    以上命令可以直接通过:btrace /dev/nvme0n1来实现。
    blkparse只是将blktrace数据转成可以人工阅读的格式,由于数据量通常很大,人工分析并不轻松,btt是对blktrace数据进行自动分析的工具。
    btt不能分析实时数据,只能对blktrace保存的数据文件进行分析

  10. btt使用

#blktrace -w 100 -d /dev/nvme0n1 
把原本按CPU分别保存的文件合并成一个,文件名为nvme.bin:
# blkparse -i nvme0n1 -d nvme0n1.bin
$ btt -i nvme0n1.log.bin
输出如下:

==================== All Devices ====================
ALL MIN AVG MAX N


Q2Q 0.000000001 0.000339658 0.031445634 694894
Q2G 0.000000124 0.000000460 0.000025725 694895
G2I 0.000000185 0.000068326 0.079106703 694864
I2D 0.000000512 0.000004411 0.000055384 694864
D2C 0.000058013 0.593889493 1.777582340 692199
Q2C 0.000062422 0.593962697 1.781217295 692199

  1. blkiomon
使用blkiomon来动态显示IO栈情况,命令如下:。
blktrace /dev/nvme0n1 -a issue -a complete -w 180  -o - |  blkiomon -I 10 -h -
其中和BLKTRACE相关的概念说明如下:
  1. I/O请求底层相关概念
一个I/O请求进入block layer之后,可能会经历下面的过程:
       Remap: 可能被DM(Device Mapper)或MD(Multiple Device, Software RAID) remap到其它设备
       Split: 可能会因为I/O请求与扇区边界未对齐、或者size太大而被分拆(split)成多个物理I/O
       Merge: 可能会因为与其它I/O请求的物理位置相邻而合并(merge)成一个I/O
       被IO Scheduler依照调度策略发送给driver
       被driver提交给硬件,经过HBA、电缆(光纤、网线等)、交换机(SAN或网络)、最后到达存储设备,设备完成IO请求之后再把结果发回。
Q – 即将生成IO请求
G – IO请求生成
I – IO请求进入IO Scheduler队列
D – IO请求进入driver
C – IO请求执行完毕
Q2G – 生成IO请求所消耗的时间,包括remap和split的时间;
G2I – IO请求进入IO Scheduler所消耗的时间,包括merge的时间;
I2D – IO请求在IO Scheduler中等待的时间;
D2C – IO请求在driver和硬件上所消耗的时间;
Q2C – 整个IO请求所消耗的时间(Q2I + I2D + D2C = Q2C),相当于iostat的await。
其中D2C可以作为硬件性能的指标;
I2D可以作为IO Scheduler性能的指标。
  1. 参考
nvme协议
http://www.nvmexpress.org/resources/specifications/
SSD工作原理
http://www.ssdfans.com/?p=131
SSD的GC和TRIM、写入放大以及性能评测
http://blog.csdn.net/scaleqiao/article/details/50511279
nvmexpress官方
http://www.nvmexpress.org/