NVMe SSD 的性能时常捉摸不定,为此我们需要打开 SSD 的神秘盒子,从各个视角分析 SSD 性能影响因素,并思考从存储软件的角度如何最优化使用 NVMe SSD,推进数据中心闪存化进程。本文从 NVMe SSD 的性能影响因素进行分析,并给出存储系统设计方面的一些思考。
存储介质的变革
近几年存储行业发生了翻天覆地的变化,半导体存储登上了历史的舞台。和传统磁盘存储介质相比,半导体存储介质具有天然的优势。无论在可靠性、性能、功耗等方面都远远超越传统磁盘。目前常用的半导体存储介质是 NVMe SSD,采用 PCIe 接口方式与主机进行交互,大大提升了性能,释放了存储介质本身的性能。通常 NVMe SSD 内部采用 NAND Flash 存储介质进行数据存储,该介质本身具有读写不对称性,使用寿命等问题。为此在 SSD 内部通过 FTL(Flash Translation Layer)解决 NAND Flash 存在的问题,为上层应用软件呈现和普通磁盘相同的应用接口和使用方式。
如上图所示,随着半导体存储介质的发展,计算机系统的 IO 性能得到了飞速发展。基于磁介质进行数据存储的磁盘和处理器 CPU 之间一直存在着棘手的剪刀差性能鸿沟。随着存储介质的演进与革新,这种性能剪刀差将不复存在。从整个系统的角度来看,IO 性能瓶颈正从后端磁盘往处理器和网络方向转移。如下图性能数据所示,在 4KB 访问粒度下,NVMe SSD 和 15K 转速磁盘相比,每秒随机读 IO 处理能力提升了将近 5000 倍;每秒随机写 IO 处理能力提升了 1000 多倍。随着非易失性存储介质的进一步发展,半导体存储介质的性能将进一步提升,并且会具有更好的 IO QoS 能力。
存储介质的革命一方面给存储系统性能提升带来了福音;另一方面对存储系统的设计带来了诸多挑战。原有面向磁盘设计的存储系统不再适用于新型存储介质,面向新型存储介质需要重新设计更加合理的存储软件堆栈,发挥存储介质的性能,并且可以规避新介质带来的新问题。面向新型存储介质重构存储软件栈、重构存储系统是最近几年存储领域的热门技术话题。
在面向 NVMe SSD 进行存储系统设计时,首先需要对 NVMe SSD 本身的特性要非常熟悉,需要了解 SSD 性能的影响因素。在设计过程中需要针对 SSD 的特性通过软件的方式进行优化。本文对 SSD 进行简要介绍,并从性能影响因素角度出发,对 NVMe SSD 进行深入剖析,在此基础上给出闪存存储设计方面的一些思考。
NVMe SSD 成为主流
NAND Flash 介质发展
目前 NVMe SSD 主流采用的存储介质是 NAND Flash。最近几年 NAND Flash 技术快速发展,主要发展的思路有两条:第一,通过 3D 堆叠的方式增加 NAND Flash 的存储密度;第二,通过增加单 Cell 比特数来提升 NAND Flash 的存储密度。3D NAND Flash 已经成为 SSD 标配,目前主流发布的 SSD 都会采用 3D NAND Flash 技术工艺。从 cell 的角度来看,目前单个 cell 可以表示 3bit,这就是通常所说的 TLC NAND Flash。今年单个 cell 的 bit 存储密度又提升了 33%,可以表示 4bit,向前演进至 QLC NAND Flash。NAND Flash 的不断演进,推动了 SSD 存储密度不断提升。截止到今天,单个 3.5 寸 SSD 盘可以做到 128TB 的容量,远远超过了磁盘的容量。下图是近几年 NAND Flash 技术的发展、演进过程。
从上图可以看出,NAND Flash 在不断演进的过程中,一些新的非易失性内存技术也开始发展。Intel 已经推出了 AEP 内存存储介质,可以预计,未来将会是非易失性内存和闪存共存的半导体存储时代。
软件层面看 SSD——多队列技术
从软件接口的角度来看,NVMe SSD 和普通的磁盘没有太多的区别,在 Linux 环境下都是标准块设备。由于 NVMe SSD 采用了最新的 NVMe 协议标准,因此从软件堆栈的角度来看,NVMe SSD 的软件栈简化了很多。在 NVMe 标准中,和传统的 SATA/SAS 相比,一个重大的差别是引入了多队列机制,如下图所示。
何为多队列技术?主机(X86 Server)与 SSD 进行数据交互的模型采用“生产者-消费者”模型,采用生产者-消费者队列进行数据交互。在原有的 AHCI 规范中,只定义了一个交互队列,那么主机与 HDD 之间的数据交互只能通过一个队列通信,多核处理器也只能通过一个队列与 HDD 进行数据交互。在磁盘存储时代,由于磁盘是慢速设备,所以一个队列也就够用了。多个处理器核通过一个共享队列与磁盘进行数据交互,虽然处理器之间会存在资源竞争,但是相比磁盘的性能,处理器之间竞争所引入的开销实在是微乎其微,可以忽略。在磁盘存储时代,单队列有其他的好处,一个队列存在一个 IO 调度器,可以很好的保证提交请求的 IO 顺序最优化。
和磁盘相比,半导体存储介质具有很高的性能,AHCI 原有的规范不再适用,原有的假设也已经不复存在,在此背景下 NVMe 规范诞生了。NVMe 规范替代了原有的 AHCI 规范,并且软件层面的处理命令也进行了重新定义,不再采用 SCSI/ATA 命令规范集。在 NVMe 时代,外设和处理器之间的距离更近了,不再需要像 SAS 一样的面向连接的存储通信网络。相比于以前的 AHCI、SAS 等协议规范,NVMe 规范是一种非常简化,面向新型存储介质的协议规范。该规范的推出,将存储外设一下子拉到了处理器局部总线上,性能大为提升。并且主机和 SSD 处理器之间采用多队列的设计,适应了多核的发展趋势,每个处理器核与 SSD 之间可以采用独立的硬件 Queue Pair 进行数据交互。
从软件的角度来看,每个 CPU Core 都可以创建一对 Queue Pair 和 SSD 进行数据交互。Queue Pair 由 Submission Queue 与 Completion Queue 构成,通过 Submission queue 发送数据;通过 Completion queue 接受完成事件。SSD 硬件和主机驱动软件控制 queue 的 Head 与 Tail 指针完成双方的数据交互。
深入理解 SSD 硬件
和磁盘相比,NVMe SSD 最大的变化在于存储介质发生了变化。目前 NVMe SSD 普遍采用 3D NAND Flash 作为存储介质。NAND Flash 内部有多个存储阵列单元构成,采用 floating gate 或者 charge trap 的方式存储电荷,通过存储电荷的多少来保持数据存储状态。由于电容效应的存在、磨损老化、操作电压干扰等问题的影响,NAND Flash 天生会存在漏电问题(电荷泄漏),从而导致存储数据发生变化。因此,从本质上讲,NAND Flash 是一种不可靠介质,非常容易出现 Bit 翻转问题。SSD 通过控制器和固件程序将这种不可靠的 NAND Flash 变成了可靠的数据存储介质。
为了在这种不可靠介质上构建可靠存储,SSD 内部做了大量工作。在硬件层面,需要通过 ECC 单元解决经常出现的比特翻转问题。每次数据存储的时候,硬件单元需要为存储的数据计算 ECC 校验码;在数据读取的时候,硬件单元会根据校验码恢复被破坏的 bit 数据。ECC 硬件单元集成在 SSD 控制器内部,代表了 SSD 控制器的能力。在 MLC 存储时代,BCH 编解码技术可以解决问题,4KB 数据中存在 100bit 翻转时可以纠正错误;在 TLC 存储时代,bit 错误率大为提升,需要采用更高纠错能力的 LDPC 编解码技术,在 4KB 出现 550bit 翻转时,LDPC 硬解码仍然可以恢复数据。下图对比了 LDPC 硬解码、BCH 以及 LDPC 软解码之间的能力, 从对比结果可以看出,LDPC 软解码具有更强的纠错能力,通常使用在硬解码失效的情况下。LDPC 软解码的不足之处在于增加了 IO 的延迟。
在软件层面,SSD 内部设计了 FTL(Flash Translation Layer),该软件层的设计思想和 log-structured file system 设计思想类似。采用 log 追加写的方式记录数据,采用 LBA 至 PBA 的地址映射表记录数据组织方式。Log-structured 系统最大的一个问题就是垃圾回收(GC)。因此,虽然 NAND Flash 本身具有很高的 IO 性能,但受限于 GC 的影响,SSD 层面的性能会大受影响,并且存在十分严重的 IO QoS 问题,这也是目前标准 NVMe SSD 一个很重要的问题。SSD 内部通过 FTL 解决了 NAND Flash 不能 inplace write 的问题;采用 wear leveling 算法解决了 NAND Flash 磨损均衡问题;通过 data retention 算法解决了 NAND Flash 长时间存放漏电问题;通过 data migration 方式解决 read diatribe 问题。FTL 是 NAND Flash 得以大规模使用的核心技术,是 SSD 的重要组成部分。
NAND Flash 内部本身具有很多并发单元,如上图所示,一个 NAND Flash 芯片由多个 Target 构成,每个 Target 包含多个 Die。每个 Die 是一个独立的存储单元,一个 Die 由多个 Plane 构成,多个 Plane 之间共享一套操作总线,多个 Plane 可以组成一个单元并发操作,构建 Multi-plane。一个 Plane 由若干个 Block 构成,每个 Block 是一个擦除单元,该单元的大小也决定了 SSD 软件层面的 GC 回收粒度。每个 Block 由多个 page 页构成,每个 Page 是最小写入(编程)单元,通常大小为 16KB。SSD 内部软件(固件)需要充分利用这些并发单元,构建高性能的存储盘。
一块普通 NVMe SSD 的物理硬件结构简单,由大量的 NAND Flash 构成,这些 NAND Flash 通过 SOC(SSD 控制器)进行控制,FTL 软件运行在 SOC 内部,并通过多队列的 PCIe 总线与主机进行对接。为了提升性能,企业级 SSD 需要板载 DRAM,DRAM 资源一方面可以用来缓存数据,提升写性能;另一方面用来缓存 FTL 映射表。企业级 SSD 为了提升性能,通常采用 Flat mapping 的方式,需要占据较多的内存(0.1%)。内存容量的问题也限制了大容量 NVMe SSD 的发展,为了解决内存问题,目前一种可行的方法是增大 sector size。标准 NVMe SSD 的 sector size 为 4KB,为了进一步增大 NVMe SSD 的容量,有些厂商已经开始采用 16KB 的 sector size。16KB Sector size 的普及应用,会加速大容量 NVMe SSD 的推广。
影响 NVMe SSD 的性能因素
NVMe SSD 厂商 Spec 给出的性能非常完美,前面也给出了 NVMe SSD 和磁盘之间的性能对比,NVMe SSD 的性能的确比磁盘高很多。但在实际应用过程中,NVMe SSD 的性能可能没有想象中的那么好,并且看上去不是特别的稳定,找不到完美的规律。和磁盘介质相比,SSD 的性能和很多因素相关,分析 SSD 的性能影响因素,首先需要大体了解 SSD 构成的主要部分。如下图所示,其主要包括主机 CPU、PCIe 互连带宽、SSD 控制器及 FTL 软件、后端 NAND Flash 带宽、NAND Flash 介质。影响 SSD 性能的主要因素可以分成硬件、软件和客观环境三大部分,具体分析如下。
硬件因素
NAND Flash 本身。不同类型的 NAND Flash 本身具有不同的性能,例如 SLC 的性能高于 MLC,MLC 的性能优于 TLC。选择不同的工艺、不同类别的 NAND Flash,都会具有不同的性能。
后端通道数(CE 数量)及总线频率。后端通道数决定了并发 NAND Flash 的数量,决定了并发能力。不同的 SSD 控制器支持不同数量的通道数,也决定了 SSD 的后端吞吐带宽能力。NAND Flash Channel 的总线频率也决定了访问 Flash 的性能。
SSD 控制器的处理能力。SSD 控制器中会运行复杂的 FTL(Flash Translation Layer)处理逻辑,将逻辑块读写映射转换成 NAND Flash 读写请求。在大数据块读写时,对处理器能力要求不是很高;在小数据块读写时,对处理器能力要求极高,处理器能力很容易成为整个 IO 系统的性能瓶颈点。
SSD 控制器架构。通常 SSD 控制器采用 SMP 或者 MPP 两种架构,早期的控制器通常采用 MPP 架构,多个小处理器通过内部高速总线进行互连,通过硬件消息队列进行通信。内存资源作为独立的外设供所有的处理器进行共享。这种架构和基于消息通信的分布式系统类似。MPP 架构的很大优势在于性能,但是编程复杂度较高;SMP 架构的性能可扩展性取决于软件,编程简单,和在 x86 平台上编程相似。不同的控制器架构会影响到 SSD 的总体性能,在 SSD 设计时,会根据设计目标,选择不同类型的 SSD 控制器。
内存支持容量。为了追求高性能,SSD 内部的映射资源表会常驻内存,映射表的内存占用大小是盘容量的 0.1%,当内存容量不够大时,会出现映射表换入换出的问题,影响到性能。
PCIe 的吞吐带宽能力。PCIe 前端带宽体现了 SSD 的前端吞吐能力,目前 NVMe SSD 采用 x4 lane 的接入方式,上限带宽为 3GB/s,当后端 NAND Flash 带宽和处理器能力足够时,前端 PCIe 往往会成为性能瓶颈点。NAND Flash 具有很高的读性能,目前来看,SSD 的读性能在很大程度上受限于 PCIe 总线,因此需要快速推进 PCIe4.0 标准。
温度对性能造成影响。在 NAND Flash 全速运行的情况下,会产生较大的散热功耗,当温度高到一定程度时,系统将会处于不正常的工作状态,为此,SSD 内部做了控温系统,通过温度检测系统来调整 SSD 性能,从而保证系统温度维持在阈值之内。调整温度会牺牲性能,本质上就是通过降低 SSD 性能来降温。因此,当环境温度过高时,会影响到 SSD 的性能,触发 SSD 内部的温度控制系统,调节 SSD 的性能。
使用寿命对性能造成影响。NAND Flash 在不断擦除使用时,Flash 的 bit error 会不断上升,错误率的提升会影响到 SSD 的 IO 性能。
软件因素
数据布局方式。数据布局方法需要充分考虑 NAND Flash 中的并发单元,如何将 IO 操作转换成 NAND Flash 的并发操作,这是数据布局需要考虑的问题。例如,采用数据交错的方式在多通道 page 上进行数据布局,通过这种方式可以优化顺序带宽。
垃圾回收/wear leveling 调度方法。数据回收、wear leveling、data retention 等操作会产生大量的 NAND Flash 后端流量,后端流量直接反应了 SSD 的写放大系数,也直接体现在后端带宽的占用。垃圾回收等产生的流量也可以称之为背景流量,背景流量会直接影响到前端用户性能。因此需要对背景流量和用户流量之间进行合理调度,使得用户 IO 性能达到最佳。
OP 预留。为了解决坏块、垃圾回收等问题,在 SSD 内部预留了一部分空闲资源,这些资源被称之为 OP(Overprovisioning)。OP 越大,GC 过程中平均搬移的数据会越少,背景流量会越小,因此,写放大降低,用户 IO 性能提升。反之,OP 越小,性能会越低,写放大会越大。在 SSD 容量较小的时代,为了提升 SSD 的使用寿命,往往 OP 都设置的比较大。
Bit error 处理影响性能。在 SSD 内部采用多种机制来处理 NAND Flash 所产生的 Bit error。ECC 纠错、read retry、soft LDPC 以及 RAIN 都是用来纠正 bit 翻转导致的错误。当 Bit 错误率增加时,软件处理的开销越大,在 bit 控制在一定范围之内,完全可以通过硬件进行纠正。一旦软件参与到 bit 纠正的时候,会引入较大的性能开销。
FTL 算法。FTL 算法会影响到 SSD 性能,对于不同用途的 SSD,FTL 的设计与实现是完全不同的,企业级 SSD 为了追求高性能,通常采用 Flat mapping 的方式,采用大内存缓存映射表;消费级 SSD 为了追求低成本,通常采用元数据换入换出的方式,并且采用 pSLC+TLC 的组合方式进行分层存储,也可以采用主机端内存缓存元数据信息,但是这些方式都会影响到性能。
IO 调度算法。NAND Flash 具有严重的性能不对称性,Flash Erase 和 Program 具有 ms 级延迟,Flash read 的延迟在 us 级。因此,如何调度 Erase、Program 以及 read 是 SSD 后端设计需要考虑的问题。另外,前端 IO 以及背景 IO 之间的调度也是需要权衡考虑,通过 IO 调度可以达到最佳性能表现。在 IO 调度过程中,还需要利用 NAND Flash 的特性,例如 Program Suspension,通过这些特性的利用,最优化 SSD 前端 IO 性能。
驱动软件。驱动软件运行在主机端,通常分为内核态和用户态两大类,内核态驱动会消耗较多的 CPU 资源,存在频繁上下文切换、中断处理,因此性能较低;用户态驱动通常采用 Polling IO 处理模式,去除了上下文切换,可以充分提升 CPU 效率,提升整体 IO 性能。
IO Pattern 对性能产生影响。IO Pattern 影响了 SSD 内部的 GC 数据布局,间接影响了 GC 过程中的数据搬移量,决定了后端流量。当 IO Pattern 为全顺序时,这种 Pattern 对 SSD 内部 GC 是最为友好的,写放大接近于 1,因此具有最好的性能;当 IO Pattern 为小块随机时,会产生较多的 GC 搬移数据量,因此性能大为下降。在实际应用中,需要通过本地文件系统最优化 IO Pattern,获取最佳性能。
客观因素
使用时间越长会导致 SSD 性能变差。使用时间变长之后,SSD 内部 NAND Flash 的磨损会加重,NAND Flash 磨损变大之后会导致 bit 错误率提升。在 SSD 内部存在一套完整的 bit 错误恢复机制,由硬件和软件两大部分构成。当 bit 错误率达到一定程度之后,硬件机制将会失效。硬件机制失效之后,需要通过软件(Firmware)的方式恢复翻转的 bit,软件恢复将会带来较大的延迟开销,因此会影响到 SSD 对外表现的性能。在有些情况下,如果一块 SSD 在掉电情况下放置一段时间之后,也可能会导致性能变差,原因在于 SSD 内部 NAND Flash 中存储电荷的漏电,放置一段时间之后导致 bit 错误率增加,从而影响性能。SSD 的性能和时间相关,本质上还是与 NAND Flash 的比特错误率相关。
环境温度也会对性能造成影响。为了控制 SSD 温度不能超过上限值,在 SSD 内部设计有一套温度负反馈机制,该机制通过检测的温度对 NAND Flash 后端带宽进行控制,达到降低温度的效果。如果一旦温度负反馈机制开始工作,那么 NAND Flash 后端带宽将会受到限制,从而影响前端应用 IO 的性能。
下面从软件的角度出发,重点阐述 GC 以及 IO Pattern 对 SSD 性能的影响。
GC 对性能的影响
SSD 内部有一个非常厚重的软件层,该软件层用来解决 NAND Flash 的问题,采用 log-structured 的方式记录数据。Log-structured 方式引入了 GC 的问题,对于前端业务来讲,GC 流量就是背景噪声。GC 流量不是时时刻刻存在的,因此,SSD 对外体现性能大幅度波动。当 SSD 为空盘时,性能会非常好,为最佳性能;当 SSD 被用过一段时间之后,性能会大幅降低。其中 GC 起到了很重要的作用。企业级 SSD 在发布 Spec 的时候,都会发布 SSD 盘的稳态性能。在性能测试的时候,需要对盘进行老化预处理。通常预处理的方法是顺序写满盘,然后再随机两遍写盘,预处理完成之后,再对盘进行随机读写测试,得到 Spec 中定义的值。稳态值基本可以认为是盘的下限性能。
上图所示是多个厂商的盘在空盘和稳态情况下的性能对比,由此可见稳态情况和空盘情况下的性能差距很大。在稳态情况下,SSD 内部的 GC 会全速运行,会占用较多的 NAND Flash 后端带宽。背景流量和前端数据流的比例也就体现了 SSD 盘的写放大系数,写放大系数越大,背景流量占用带宽越多,SSD 对外体现的前端性能也就越差。写放大系数很多因素相关,例如 OP、应用 IO Pattern 等。如果应用 IO Pattern 比较好,那么可以降低写放大系数,背景噪声流就会减少,前端业务的性能会提升。例如,在 SSD 完全顺序写入的情况下,写放大系数可以接近于 1,此时 GC 产生的数据流很少,背景流量基本没有,后端带宽基本被业务数据流占用,因此对外体现的性能会很好。
GC 是影响性能的重要因素,除了影响性能之外,GC 会增大写放大,对 SSD 的使用寿命产生影响。从软件层面的角度考虑,可以通过优化应用 IO Pattern 的方式优化 SSD 内部 GC,从而进一步提升 SSD 的性能,优化使用寿命。对于下一代更为廉价的 QLC SSD 介质,就需要采用这种优化思路,否则无法很好的满足实际业务的应用需求。
IO Pattern 对性能的影响
IO Pattern 会对 SSD 的性能产生严重影响,主要表现在如下几个方面:
不同的 IO Pattern 会产生不同的写放大系数,不同的写放大系数占用后端 NAND Flash 带宽不同。当前端应用对 SSD 采用完全顺序的方式进行写入时,此时是最佳的 IO Pattern,对于 SSD 而言写放大系数接近 1,SSD 内部的背景流量基本可以忽略,前端性能达到最佳。在实际应用中,很难采用这种完全顺序的数据写模型,但可以通过优化逼近顺序写入。
1, 不同请求大小的 IO 之间会产生干扰;读写请求之间会产生干扰。小请求会受到大请求的干扰,从而导致小请求的延迟增加,这个比较容易理解,在 HDD 上同样会存在这种情况。由于 NAND Flash 介质存在严重的读写不对称性,因此读写请求之间也会互相干扰,尤其是写请求对读请求产生严重的性能影响。
顺序写入 Pattern 对 SSD 性能优化的奥秘
在针对闪存系统的设计中,需要考虑 IO Pattern 对性能产生的影响,通过软件的优化来最优化 SSD 的使用。在实际应用中完全顺序写入的 IO Pattern 基本上是不存在的,除非用作顺序写入的日志设备。对于顺序写入优化性能这个结论,需要从 SSD 内部实现来深入理解,知道根源之后,可以采用合理的方式来逼近顺序写入的模式,从而最优化 SSD 的性能。
SSD 内部采用 log-structured 的数据记录模式,并发写入的 IO 数据按照时间顺序汇聚成大数据块,合并形成的大数据块以 Page stripe 的方式写入 NAND Flash。多个 Page stripe 会被写入同一个 GC 单元(Chunk or Superblock),当一个 GC 单元被写完成之后,该 GC 单元进入 sealed 模式(只读),分配新的 GC 单元写新的数据。在这种模式下,如果多个业务的数据流并发随机的往 SSD 中写入数据,那么多个应用的数据就会交错在一起被存储到同一个 GC 单元中。如下图所示,不同应用的数据生命周期不同,当需要回收一个 GC 单元的时候,会存在大量数据的迁移,这些迁移的数据就会形成写放大,影响性能和使用寿命。
不同应用的数据交错存储在同一个 GC 单元,本质上就是不同冷热程度的数据交错存储的问题。从 GC 的角度来讲,相同冷热程度的数据存储在同一个 GC 单元上是最佳的,为此三星推出了 Multi-stream SSD,该 SSD 就允许不同应用的数据存储到不同的 Stream 单元(GC 单元),从而提升 GC 效率,降低写放大。Multi-stream 是一种显式的设计方式,需要更改 SSD 接口以及应用程序。从 IO Pattern 的角度考虑,可以通过顺序大块的方式也可以逼近类似的效果。假设操作 SSD 只存在一个线程,不同的应用都采用大数据块的方式写入数据,那么在一个时间片段内只存在一个应用的数据往 SSD 中写入数据,那么在一个 GC 单元内存储的数据会变得有序和规则。如下图所示,采用上述方法之后,一个 GC 单元内存储的数据将会变得冷热均匀。在 GC 过程中会大大减少数据的搬移,从而减少背景流量。
在实际应用中,上述 IO Pattern 很难产生,主要是应用很难产生非常大粒度的请求。为此在存储系统设计过程中,可以引入 Optane 高性能存储介质作为 SSD 的写缓存。前端不同业务的写请求首先写到 Optane 持久化介质中,在 Optane 持久化介质中聚合形成大数据块。一旦聚合形成大数据块之后,再写入 SSD,通过这种方式可以最大程度的逼近 SSD 顺序写入过程,提升 SSD 的性能和使用寿命。
读写冲突 Pattern 对性能的影响
如下图所示,NAND Flash 介质具有很强的读写不对称性。Block Erase 和 Page Program 的延迟会远远高于 Page Read 所耗费的时间。那么在这种情况下,如果 read 请求在同一个 Flash Channel 上和 Erase、Program 操作冲突,那么 read 操作将会被 Erase/program 操作影响。这是在读写混合情况下,读性能会受到影响的重要因素。
在实际应用过程中,经常会发现应用的测试结果和 SSD Spec 对不上,会比 Spec 给出的值要来的低。Spec 给出的值通常为纯读或者纯写情况下的性能指标,在读写混合的场景下,性能表现和 Spec 给出的值就会存在非常大的出入。
对于不同的 SSD,通过测试可以发现在读写混合情况下的性能表现差距会比较大。在 SSD 处于稳态条件下,应用随机读的情况下,如果引入一个压力不是很大的顺序写,那么会发现不同 SSD 的抗干扰能力是不同的。有些 SSD 在写干扰的情况下,读性能会急剧下降,延迟快速上升,QoS 性能得不到保证。下图是两个 SSD 在相同情况下的测试结果,从结果来看,有些 SSD 的抗写干扰能力比较强,读性能不会急剧下降。
为什么有些 SSD 会具备比较强的抗写干扰能力呢?其中的奥秘就在于 SSD 内部的 IO 调度器。IO 调度器会对 write、read 和 Erase 请求进行调度处理,该调度器算法的不同就会表现出不同的抗干扰能力。目前很多 NAND Flash 可以支持 Program/Erase Suspension 的功能,在 IO 调度处理的过程中,为了提升读性能,降低读请求延迟,可以采用 Suspension 命令对 Program/Erase 命令暂停,对 read 请求优先调度处理。
读写冲突是 SSD 内部影响 IO QoS 的重要因素。在 SSD 内部通过 IO 调度器的优化可以提升 SSD 性能的 QoS 能力,但是还是无法与存储软件结合来协同优化 QoS。为了达到最佳的 SSD 性能 QoS,需要关注 Openchannel 技术。Openchannel 其实只是一种软硬件层次划分的方法,通常来讲,SSD 内部的逻辑可以划分为面向 NAND 资源的物理资源管理层以及面向数据布局的资源映射层。物理资源管理由于和 NAND Flash 密切相关,因此可以放到 SSD 内部。传统的 NVMe SSD 需要对外暴露标准的块设备接口,因此需要在 SSD 内部实现资源映射层。从端至端的角度来看,资源映射层可以与存储软件层结合起来,为此将资源映射层从 SSD 内部剥离出来,集成至存储软件层。一旦资源映射层从 SSD 内部剥离之后,需要定义一个新的 SSD 接口,其中的一种接口方式就是 Openchannel。
盘古分布式存储针对 SSD QoS 问题进行了大量研究,提出了 Object SSD 的概念,Object SSD 也是一种新的 SSD 接口方式,其采用对象方式对 SSD 进行读写删操作,每个对象采用 Append write 操作方式。这种接口方式可以很好的与分布式存储无缝结合。采用 Object SSD 之后,SSD 内部的大量工作被简化,IO 的调度会更加灵活,存储软件与 SSD 协同配合,达到 IO 性能的最优化,以及 QoS 的最大化。
SSD 写性能分析模型
SSD 内部的数据流分成两大类,一类为前端用户数据流;另一类为内部背景数据流。前端用户数据流和背景数据流会汇聚成 NAND Flash 后端流量。当背景数据流不存在时,NAND Flash 带宽会被用户数据流全部占据,此时 SSD 对外表现的性能达到最佳。当 SSD 具有较大写放大时,会产生很大的背景数据流,背景流会抢占 NAND Flash 带宽,导致前端用户 IO 性能降低。为了稳定前端 IO 性能,在 SSD 内部的调度器会均衡前端和背景流量,保证前端性能的一致性。背景流量的占比反应了 SSD 的写放大系数,因此,站在 NAND Flash 带宽占用的角度可以分析 SSD 在稳态情况下的性能。
在此,假设写放大系数为 WA,顺序写情况下的总带宽数为 B,用户写入流量(随机写入流量)为 U。那么,由于 GC 写放大造成的背景流量为:(WA - 1)* U
写放大流量为一读一写,都会占用带宽,因此,总带宽可以描述为:
2 * (WA - 1) * U + U = B
因此,可以得到:
U = B / (2*(WA - 1) + 1) = B / (2 * WA - 1)
上述公式表述了前端用户流量和 NAND Flash 总带宽、写放大系数之间的关系。
根据 Spec,Intel P4500 的顺序写带宽为 1.9GB/s,按照上述公式,在随机访问模式下的带宽为: 1900 / (2 * 4 - 1) = 270MB/s,IOPS 为 67K,根据该公式推导的结果和 Spec 给出的结果相同。
下图是 Intel P4500 和 Samsung PM963 随机写延迟和推导公式之间的对比。结果非常吻合。
由此可以推出,随机写性能由 SSD 内部后端带宽以及写放大系数来决定。因此,从存储软件的角度出发,我们可以通过优化 IO Pattern 的方式减小写放大系数,从而可以提升 SSD 的随机写性能。
小结
闪存存储技术正在飞速发展,闪存介质、SSD 控制器、存储系统软件、存储硬件平台都在围绕闪存日新月异的发展。闪存给数据存储带来的价值显而易见,数据中心闪存化是重要发展趋势。NVMe SSD 性能受到很多因素的影响,在软件层面可以通过 IO Pattern 优化 SSD 的性能,使得整体存储系统的性能达到最佳。
作者简介
吴忠杰(储道),专注存储技术研发十多年,历经中科院计算所存储研究中心、EMC、Memblaze 著名存储研发机构,从传统存储阵列、虚拟化集群存储、数据去重、闪存存储一直做到大规模分布式存储。长期从事存储前沿技术的研究与开发,精通软、硬件技术,发表十余篇学术论文,拥有多项海内外存储技术专利,是“存储之道”技术博客作者。他是盘古分布式存储资深技术专家储道。
评论 1 条评论