在过去的几年中,一种新型存储设备已经进入笔记本电脑和数据中心,从根本上改变了人们对存储的功耗、尺寸和性能动态的期望。固态硬盘 (SSD) 是一项已经存在超过 30 年的技术,但由于价格过于昂贵而未能得到广泛采用。
随着 Apple iPad 和 iPhone 等消费类产品的推出,情况发生了变化,这导致廉价的非易失性存储器得到广泛应用。制造商已经使用这种消费级材料来生产固态硬盘,并使它们在外观和行为上尽可能地像硬盘驱动器 (HDD)。然而,在表面之下,它们完全不同。
硬盘驱动器使用安装在机械驱动器上的磁头来访问旋转的磁存储介质。相比之下,固态硬盘使用非易失性存储器(即 NAND 闪存)作为其存储介质。缺少移动部件以及使用硅作为介质使该设备获得了“固态”的名称。此属性使固态硬盘比硬盘驱动器更不易损坏。因此,固态硬盘在智能手机和数码相机等移动设备中很常见。
SD(安全数字)和 CF(CompactFlash)存储卡是固态硬盘的更小、更简单的版本。选择使用固态硬盘还是不太复杂的设备的关键变量是应用程序的性能要求。数码相机对存储的需求远低于多核笔记本电脑或服务器。这些差异对固态硬盘的设计产生重大影响。
硬盘驱动器和固态硬盘都是当今计算机系统中非易失性存储的核心构建块,它们都属于块设备类。这些设备使用逻辑寻址来访问数据并抽象物理介质,使用小的、固定的、连续的字节段作为可寻址单元。每个块设备由三个主要部分组成:存储介质、用于管理介质的控制器以及用于访问介质的主机接口。
存储介质是固态硬盘性能和成本优势背后的关键因素。大多数固态硬盘都围绕广泛使用的 NAND 闪存构建,NAND 闪存于 1980 年代后期开发,作为一种基于电子的陷阱电荷存储介质。NAND 单元将电子无限期地存储在电容器上,处于无电源状态。然后,通过 NAND 芯片上的电路感应电荷。
写入 NAND 闪存是通过使用高压脉冲将电子添加到(编程)或从(擦除)存储单元来完成的。NAND 闪存通过使用简单的模数转换器读取,方法是将偏置电压施加到单元。
不同类型的闪存使用不同数量的阈值来确定单元中的值。SLC(单层单元)存储单个数据位,并具有两个阈值。MLC(多层单元)存储两位数据,并具有四个阈值。更新的闪存存储器,称为 TLC(三层单元),能够存储三位值,并具有八个或更多阈值。通常,n 位模数转换器的值可以描述为
n = log2(#阈值电压)
写验证操作用于编程或擦除 NAND 闪存。将高压脉冲施加到单元,并重复此过程,直到将正确的值编程到单元中。这种技术的最大缺点是单元必须先擦除才能重新编程。此外,闪存单元支持的层数越多,高压脉冲必须越小、越精确。使这些脉冲更精确会减慢闪存的编程速度并降低其写入性能。
磁盘驱动器使用对称访问——最小读取和写入访问大小相同。另一方面,NAND 闪存与大多数非易失性存储器一样,使用非对称访问——介质的最小读取和写入大小不同。这种不对称性是存储器阵列架构的结果。与大多数存储器一样,NAND 由二维阵列组成,其中位线作为访问的一个维度,字线作为另一个维度。NAND 的不同之处在于多个单元共享位线。此 NAND 串由 32-64 个单元组成。最小读取通常是 8 KB 页面,基于字线长度。对阵列的写入需要线性编程 NAND 串上的所有页面,使最小写入大小为 32-64 页。这称为程序/擦除块。
晶粒是硅晶片,由大约 4,000 个块的一个到四个存储器阵列以及使阵列可用的必要元件组成。这些非存储元件包括:用于管理存储器阵列上的操作的控制器逻辑;用于编程和读取阵列的高压发生器;用于从单元读取阈值的感应检测器;用于临时存储进出存储器阵列的数据位的缓存缓冲区;以及用于从晶粒读取和写入数据的高速接口。
单个晶粒能够以高达 400 MB/秒的速度读取,但由于编程的复杂性,写入速度仅为 10-20 MB/秒。延迟是 NAND 闪存的主要优势。读取的典型延迟为 20-200 微秒,写入的典型延迟为 1-10 毫秒。此性能优于硬盘驱动器,硬盘驱动器的读取和写入通常都以数十毫秒为单位衡量。
NAND 闪存晶粒的容量相对较小,每个晶粒最多可容纳 16 GB。固态硬盘包含 8-256 个晶粒,以满足计算的存储要求。由于多个晶粒将同时处于活动状态,因此更大容量的固态硬盘往往会产生更好的性能。然而,多个活动晶粒可能会导致散热问题,因为每个晶粒中的高压发生器效率低下。在繁重的程序和擦除操作期间,固态硬盘会限制活动晶粒的数量,以避免过热或过度的峰值电流消耗。
基于电子的存储具有许多限制,所有存储介质也是如此。最大的限制存在于程序和擦除操作中。随着时间的推移,高压脉冲会烧毁氧化层,从而降低单元隔离电子的能力。电子也会被困在氧化层中,增加阈值测量的电阻,并导致误读单元的阈值。
烧毁是 NAND 闪存最容易被误解的属性。制造商通常会出于保修目的而指定每个单元建议的程序和擦除周期数,但不指定单元将保留数据的时间量。即使没有过度使用,存储的电子最终也会从单元中消散,并且数据将丢失。程序和擦除周期数只会加速数据消失之前的时间。数据可以在轻度循环的单元中保留数年,而重度循环的单元可能仅保留几个月的数据。长时间暴露于高温也会加速数据的衰减。多次读取相同的 NAND 块会导致电子逸出,从而改变单元内存储的值,从而导致称为读取干扰的故障机制。
随着制造技术的进步,允许单元尺寸缩小并降低成本,每个单元存储的电子数量以及每个单元的隔离氧化物尺寸都在缩小。这使得很难与上一代的性能和寿命相匹配。这些限制以及许多其他限制,使 NAND 闪存本身成为一种不切实际的存储技术。然而,对于固态硬盘来说,烧毁、数据衰减和读取干扰是可解决的问题,因为不断且一致地移动数据可以防止此类故障。因此,NAND 闪存和控制器之间必须建立共生关系,才能管理和解决介质的不完善之处。
闪存控制器是使不完善的 NAND 闪存变得强大可靠的关键组件。控制器是一个复杂的嵌入式系统,具有独立的处理和固件,用于管理固态硬盘的所有方面。它旨在保护和控制底层的 NAND 闪存介质。
与磁盘驱动器一样,闪存控制器最常实现为 SoC(片上系统)设计。控制器由多个硬件加速功能块组成,这些功能块耦合到一个或多个嵌入式处理器内核。这些都位于单个 ASIC(专用集成电路)芯片内,以提供最低的控制器成本。ASIC 中包含用于执行固态硬盘固件的大型 SRAM(静态 RAM),但通常使用外部 DRAM(动态 RAM)来缓存用户数据和内部固态硬盘元数据。高端固态硬盘包括电池或电容器的备用电源系统,以确保在意外断电期间将易失性缓存中的用户数据刷新到 NAND 阵列。
主机接口是从主机系统到固态硬盘的物理接口。大多数固态硬盘利用现有的存储标准和接口,例如 SATA(串行 ATA)和 SAS(串行连接 SCSI)。它们使用传统的块访问协议。底层原语和高速串行器/解串器在硬件中加速,高级块访问协议由在嵌入式处理器上运行的固件实现。
用于固态硬盘的一种较新的存储接口,硬盘驱动器未使用,是 PCIe(外围组件互连高速)。这与笔记本电脑和服务器上使用的通用 I/O 接口相同。此接口是一种更高效的互连,因为它允许系统逐步淘汰主机总线适配器,主机总线适配器是 SATA 和 SAS 设备上所需的附加控制器,用于转换这些总线协议。移除这些总线控制器可降低延迟和功耗。
闪存通道是专用于与固态硬盘上 NAND 闪存物理子集通信的控制器和接口电路。NAND 晶粒通过并行 I/O 接口连接到控制器,该接口能够提供 400 MB/秒的吞吐量。此接口由四到八个 NAND 晶粒共享,一次只能有一个晶粒与闪存通道控制器通信。
具有多个存储器阵列的 NAND 晶粒能够同时执行多个操作,但它们并非完全独立。晶粒和通道控制器使用轻量级协议,其中数据在 NAND 晶粒上的缓冲区之间传输。控制器必须管理并正确地对通道上所有晶粒的读取、编程和擦除操作进行排序,以实现最佳利用率。复杂的阵列操作(例如程序和擦除)将使单个存储器阵列或平面处于繁忙状态,直到操作完成。这可能需要长达数十毫秒的时间。一些固态硬盘控制器具有专用硬件排序器或微控制器,可以重新排序晶粒操作以获得最佳性能。
最常见的固态硬盘配置是八个通道,但固态硬盘控制器可以有 4-32 个通道来满足性能要求。
NAND 闪存具有更高的性能,但与其他存储介质相比,也具有更高的误码率。更高的误码率要求固态硬盘以每秒千兆字节的速度纠正位错误,这相当于 NAND 闪存的速度。因此,负责编码和解码所有闪存读取和写入操作的纠错硬件通常是固态硬盘控制器的最大部分。一些控制器为每个闪存通道实现一个 ECC(纠错码)硬件引擎,以提高并行性能,而另一些控制器则实现一个由所有通道共享的 ECC 引擎,以降低成本。
最常用的 ECC 是 BCH(Bose Chaudhuri Hocquenghem)。它因其速度和易于实现而受到青睐,但这以 ECC 所需的冗余存储效率低下为代价。
闪存晶粒设计人员对给定一代 NAND 闪存所需的 BCH 可纠正性做出假设,并在每个页面和块内添加冗余空间以解决此问题。随着晶粒随着每一代闪存的缩小,错误数量和纠错需求都在增长;过去五年中,纠错(而非存储)所需的最小开销增加了五倍。
此外,仅使用 BCH 的控制器设计在历史上假设位故障是均匀的。较新的技术基于对 NAND 闪存晶粒内位故障特性和数据局部性的更好理解,提供了更高的效率和可纠正性。
LDPC(低密度奇偶校验)代码方法以及来自 NAND 晶粒的更高级信息的使用,使可纠正性比以前的 BCH 方法提高了 8-10 倍。然而,LDPC 也有一些缺点:纠错性能较慢;它需要大量的控制器芯片空间来实现;并且 NAND 芯片设计人员通常不愿共享使 LDPC 有效工作所需的信息,因为所需的参数数据通常被认为是商业秘密。控制器可能同时包含 BCH 和 LDPC 功能,并且仅在 BCH 技术失败时才使用 LDPC,从而确保快速性能和高数据可靠性。
另一种来自 HDD 阵列的新颖纠错方法是在一组 NAND 晶粒上使用 XOR 奇偶校验。这项技术应该产生更好的纠错能力,并且能够承受完整的 NAND 晶粒故障。此外,数据加扰器用于在将数据写入晶粒之前对数据进行“白化”。白化数据可防止将某些用户数据模式写入 NAND 晶粒,这些模式可能会导致高位故障,这些故障是由存储器阵列中相邻单元之间的干扰引起的。
固态硬盘本质上在控制器内部运行着一个复杂的文件系统。运行此文件系统的固件是当今不同固态硬盘之间的关键区别之一。
FTL(闪存转换层)的主要功能是将来自系统的逻辑块映射到物理 NAND 页面和块。由于 NAND 闪存的非对称 I/O 访问限制,此映射面临处理多种大小的请求和对齐方式的挑战。系统使用由 512 字节或 4 KB 组成的逻辑块,然后将其映射到 8 KB NAND 页面,最后需要将其写入由 64 或 128 个页面组成的块。
固态硬盘没有处理此问题的标准技术。一种常见方法是将连续的逻辑块静态映射到 NAND 页面大小的页面对齐分配单元中。一旦固态硬盘有足够的分配单元,它们就会组合成 NAND 块大小单元,然后再写入闪存。当今大多数固态硬盘都使用 LFS(日志结构文件系统)的衍生版本作为 FTL 的基础,因为考虑到 NAND 闪存的先擦除后编程限制,仅附加写入设计效果良好。
由于写入只能写入空块,因此 FTL 必须维护一个空闲块池。如果 FTL 耗尽空闲 NAND 块,或者固态硬盘在一段时间内处于非活动状态,则固件将开始执行后台垃圾回收操作以回收稀疏填充的 NAND 块。通过将数据合并到新块并擦除旧块来回收这些块,从而创建一个空闲块池供 FTL 使用。
早期的固态硬盘性能不一致,尤其是在过度压力下,因为垃圾回收要么耗尽块,要么使用通道/芯片带宽。当今的固态硬盘过度配置物理 NAND 闪存,以确保有足够的空闲块来防止垃圾回收造成的性能损失。大多数消费级固态硬盘过度配置不到 5% 的额外 NAND 闪存,而企业级固态硬盘则为性能关键型应用程序过度配置高达 50%。固态硬盘基准现在考虑了垃圾回收的影响,并且在进行性能测量之前需要对 FTL 进行预处理。
尽管 NAND 闪存存在物理挑战,但 FTL 使用多种方法来优化性能
• 固件跟踪每个 NAND 块已编程和擦除的次数,并将写入均匀分布在固态硬盘中的所有 NAND 块上,从而延长固态硬盘的寿命。
• 芯片制造过程中,芯片中的某些 NAND 块存在缺陷。此外,块在固态硬盘运行期间可能会变坏。FTL 必须跟踪这些坏块并替换好块。
• NAND 块根据其中数据的存在时间标记为垃圾回收,以避免数据保留问题。
• FTL 优化吞吐量和芯片使用率。一种常见的方法是在多个通道上静态交错分配单元,以确保最佳吞吐量,并尽可能多地填充各个块。
由于硬盘驱动器一直被认为是主要的存储介质,因此当今的软件和硬件都经过工程设计,旨在优化这些存储设备的性能
• 文件系统和应用程序使用复杂的启发式方法来尽可能短地移动机械磁盘头,从而改善读取和写入。
• 相邻的请求在一个称为 I/O 合并的过程中合并成一个更大的请求,从而构建硬盘驱动器最擅长处理的大型顺序写入。
• 还有一种假设,即硬盘驱动器将使用线性逻辑寻址,其中地址范围的开头是磁盘盘片的外径(驱动器速度最快的部分),地址范围的结尾是内径(驱动器速度最慢的部分)。
然而,这些技术并未优化固态硬盘的使用,并且可能会阻碍固态硬盘的性能
• 在固态硬盘中,逻辑寻址最终是完全随机的,这取决于写入访问模式以及 FTL 如何将数据放置在 NAND 闪存上。这使得基于局部性的算法失效。
• 向固态硬盘排队大量 I/O 请求可能会导致延迟和性能不一致(I/O 合并和磁盘头放置的优化都需要大量 I/O 请求排队)。
需要重写文件系统和应用程序,才能真正利用固态硬盘可以提供的性能和优势。Linux 在优化固态硬盘调度方面做得最多。操作系统具有用于关闭 I/O 合并和基于局部性的调度启发式方法的调整参数,从而提高了固态硬盘的可预测性和性能。
文件系统和应用程序的一些新接口添加打破了硬盘驱动器仿真模型,并有助于提高固态硬盘性能
•TRIM/UNMAP。 固态硬盘的一个常见问题是,主机文件系统可能会擦除空闲数据,但无法告知存储设备它不再需要该数据。TRIM/UNMAP 接口允许固态硬盘清除 FTL 中的 LBA(逻辑块寻址)条目,从而为其提供更多可用空间用于垃圾回收并减少写放大。OS/X、Microsoft Windows 和 Linux 都已实现 TRIM。
•Scatter Gather。 块访问命令协议将请求限制为单个连续的逻辑块范围,这需要对固态硬盘服务的小型随机请求进行过多的命令开销。Scatter Gather 添加了用于将多个不连续的请求“收集”到单个命令中的命令,从而减少开销并提高性能。
虽然固态设计显然受益于驱动器行业开创的一些数据管理技术,但随着我们从为旋转机械存储设计的计算机系统世界转向全固态存储世界,硬盘驱动器仿真模型将被打破。
未来,NAND 闪存存储器将不可避免地达到物理极限。NAND 芯片不断缩小以降低成本,从而产生耐用性和可靠性问题,这些问题无法通过固态硬盘控制器或固件来弥补。仍处于起步阶段的较新存储器技术(例如 PCM(相变存储器)和 ReRAM(阻变式 RAM))在超越此类限制方面显示出巨大的希望。它们的部分原因是通过摆脱固态硬盘中使用的 NAND 闪存的先擦除后编程和非对称访问要求来实现的。
反过来,这种进步将不可避免地继续在从旋转介质到固态设备的过渡中看到的进化/革命范式。这些新型介质无疑将借鉴和建立在基于 NAND 的固态硬盘中实现的技术之上。与此同时,向这些更新技术的转变将需要超越当今开发的用于应对 NAND 独特挑战的技术。需要构建新的编程模型和接口,以充分利用提供 DRAM 速度和闪存数据保留的新型存储介质。
喜欢还是讨厌?请告诉我们
Michael Cornwell 是 Pure Storage 的技术和战略总监。他之前曾在 Sun Microsystems 工作,担任闪存首席技术专家,并领导创建了当时世界上最快的存储系统 Sun Storage F5100 Flash Array。在加入 Sun 之前,他曾担任 Apple iPod 部门的存储工程经理,在那里他为 Apple 产品采用 NAND 闪存发挥了重要作用。他之前曾在 Quantum Corporation 担任存储架构师。他拥有加州大学圣克鲁斯分校的计算机科学学士学位。他获得了 45 项美国闪存和其他存储技术专利。
© 2012 1542-7730/11/1000 $10.00
最初发表于 Queue vol. 10, no. 10—
在 数字图书馆 中评论本文
Pat Helland - 关注你的状态以保持心态
应用程序在进入分布式和可扩展世界时,经历了有趣的演变。同样,存储及其表亲数据库也与应用程序并肩发展。很多时候,存储和应用程序的语义、性能和故障模型都会随着业务需求和环境挑战的变化而发生微妙的舞动。向组合中添加规模确实激起了波澜。本文着眼于其中的一些问题及其对系统的影响。
Alex Petrov - 现代存储系统背后的算法
本文仔细研究了现代数据库中使用的两种存储系统设计方法(读取优化的 B 树和写入优化的 LSM(日志结构合并)树),并描述了它们的使用案例和权衡取舍。
Mihir Nanavati, Malte Schwarzkopf, Jake Wires, Andrew Warfield - 非易失性存储
对于大多数执业计算机科学家的整个职业生涯,一个基本的观察结果始终成立:CPU 的性能明显高于 I/O 设备,价格也更高。CPU 可以极高的速率处理数据,同时为多个 I/O 设备提供服务,这一事实对各种规模系统的硬件和软件设计都产生了深远的影响,几乎从我们开始构建它们以来就是如此。
Thanumalayan Sankaranarayana Pillai, Vijay Chidambaram, Ramnatthan Alagappan, Samer Al-Kiswany, Andrea C. Arpaci-Dusseau, Remzi H. Arpaci-Dusseau - 崩溃一致性
数据的读取和写入是任何冯·诺依曼计算机最基本的方面之一,但它却出奇地微妙且充满细微差别。例如,考虑在具有多个处理器的系统中访问共享内存。虽然程序员最容易理解的简单直观的方法(称为强一致性)是程序员最容易理解的,但许多较弱的模型正在广泛使用(例如,x86 总存储顺序);这些方法提高了系统性能,但代价是使对系统行为的推理更加复杂且容易出错。