文章转载自:数据存储张 公众号
随着SSD价格的持续走低,SSD在整个存储产品中的比重越来越大,很多公司推出了全闪磁盘阵列。比如EMC的PowerStore、华为的Dorado和Pure Storage等。从外观上来说,SSD硬盘不像机械硬盘那样只有盘状规格,SSD规格非常多,比如PCIe卡规格、M.2规格和盘规格,如图所示。
对于外观我们不做过多介绍,今天我们将深入SSD的内部,更加详细的介绍其内部的硬件结构和软件架构,以及SSD的数据读写相关的特性。
SSD的内部结构
对于SSD硬盘的内部结构如图所示,其中内部包括三个核心的组件,分别是控制器、缓存和闪存颗粒。其中控制器类似我们计算机的CPU,缓存则类似内存,而闪存颗粒则是持久化的存储介质,类似机械硬盘的盘片。
除了上述核心组件外,需要一个接口与主机建立连接,称为主机接口。接口有多种不同的规格,比如SATA、SAS和NVMe等。
闪存控制器
其实SSD设备本身就是一台迷你计算机,控制器可以理解为其CPU,它是SSD的心脏和大脑。控制器建立了主机与SSD中其它组件之间的关联。当主机想要将数据发送到SSD时,闪存控制器会指示数据流以确保其可靠的存储和检索。它还包含管理SSD的固件,并执行后台处理,例如管理闪存文件系统,损耗均衡,纠错,修剪和垃圾回收。
易失性内存
这个组件类似计算机中的内存,其实也是SSD的内存,用作临时数据存储。并非所有SSD都有该部件,但企业级SSD通常具备该部件。因为它是易失的,所以需要电力来保留信息。控制器中的固件决定何时将数据从易失性(非持久性)存储器刷新或移动到非易失性(持久性)闪存。在意外断电的情况下,除非有效的电源故障保护机制可用,否则缓存中的数据可能会丢失或损坏。
非易失闪存
数据持久存储在NAND闪存芯片中并从中检索。它们是非易失性的,因为即使SSD没有电源,它们也会保留数据。
SSD的逻辑结构
即使一个非常小的闪存颗粒内部也是非常复杂的。如图所示,我们将一个闪存颗粒放大,可以看到其内部的主要构成(这里是逻辑构成)。理解这部分的内容对我们理解后续的关于SSD的访问特性非常有帮助。
我们看到的芯片颗粒实际上是对闪存封装而成的,真正起作用的是内部的晶体芯片。在每个封装中可能有一个或者多个晶体芯片,这个芯片称为Die。每个Die中会有若干个Plane,而Plane中会有很多Block,Block中包含的是Page。其中,Block是进行数据擦除的最小单元,而Page是SSD读写的最小单元。
以Micron(镁光)生产的某128Gb的闪存颗粒为例,其中每个Die有2个Plane,每个Plane有1024个Block,每个Block有512个Page。其中页的大小是16KB。根据这些数据我们可以计算得到,Block的大小为16KB*512 = 8MB,Plane的大小为8MB*1024=8GB,因此Die的大小为16GB,也就是128Gb。
可以看到上述芯片最小的写单元是16KB,而最小的擦除单元是8MB。这些内容大家需要注意,在以后软件设计中需要非常注意。
SSD的访问特性
前面我们介绍到SSD读写的最小单元是Page,擦除的最小单元是Block。以上文设备为例,在应用程序写数据时,最小粒度是16KB,即使写入1字节的数据,在SSD内部也是要占用16KB的空间。同时,如果想继续在相邻的位置再写入1字节数据时,无法对原来的页进行改写,必须选择一个新页,同时原来的页也会被标记为释放状态。当一个Block里面的所有页都被释放后,我们无法直接改写其中的任何一个页,需要擦除整个8MB的Block才可以重新写数据。上述页和块的大小与设备的规格相关,不同厂商的产品有所差异。
SSD的读写特性与机械磁盘的特性有着非常大的差异。对于机械磁盘来说,其访问的最小粒度是扇区(512B),且可以在原地实现数据的改写。但SSD却无法原地修改数据,并且其写数据的最小粒度也比机械磁盘大很多。
由于上述两个特性,在访问SSD的时候就会存在相应的问题。以写粒度为16KB为例,如果我们业务IO的大小非常小,比如1KB左右,且是随机IO的话。由于位置偏移大,且数据粒度小,将导致1KB的数据占用16KB的页,形成很大的空间浪费。
如图所示,第一个IO将使用一个页来存储数据,第二个IO时又需要找一个新的页在存储数据。依次类推,当整个块(8MB)写满的时候,实际才写入的了512KB的数据(8MB/16)。
前文已述,SSD无法在原地进行数据修改,如果改动的内容小于页的大小将导致写放大问题。在块内部,如果有剩余的页空间,在修改数据的时候将分配新的页来承载数据。如图所示,绿色方块为原始数据,当修改其中的数据时,将分配一个新页来存储修改后的数据,而原来的页将被标记为释放状态。
对于上述过程,由于修改的数据可能非常小(比如1KB),那么为了保证原始页数据不丢失,首先需要读出数据,然后进行合并操作,最后写入新的位置。
正是由于这些读写特性导致SSD硬盘存在读写放大的问题。以写放大为例,如果用户层面写入10B的数据,在SSD内部来说都需要写入一个Page,也就是16KB的数据。而如果需要改动数据,则需要先从原始位置读取数据,合并后才可以写入新的位置。
另外一个导致写放大的原因在于空间释放(GC)。由于SSD无法在原地修改,因此当一个块中的页被使用并释放后,其空间并非可用状态。必须对整个块进行擦除后才可以重新被使用。问题是一个块中很难保证所有页都是释放的,因此在擦除之前需要将有数据的页迁移到其它块中。
如图所示,当SSD中其中2个块的大部分页都处于释放状态时(本文是一个示例,实际情况要复杂的多),SSD控制器会进行垃圾回收动作(GC)。此时,这两个块中的有效数据会被移动到新的块中,当完成数据移动后,控制器会对前面的块进行擦除操作。由于在空间释放的时候总是要迁移一些数据,这将导致额外的数据读写操作。
基于上述特性,在应用层面访问SSD时就需要进行综合考虑,比如写数据的时候尽量凑够一个页,尽量避免原地修改等。除此之外,SSD还有擦写次数的限制,也就是当块的擦写达到规定次数后就无法再存储数据了。基于上述特性,现有的文件系统和RAID的设计其实不太适应SSD硬盘。以Ext4为例,当访问文件时,inode节点中的访问时间和文件大小等信息会被频繁更新,这将导致SSD磨损加剧。
今天我们主要介绍了SSD的内部结构及写放大问题。这些特性对于我们使用SSD(基于SSD做开发)有很大的帮助,我们后面会结合实例介绍一下软件层面是如何应对SSD的这些特性的。