如果仅仅是SSD的使用者,一定不会在意在SSD内部居然还存在一个复杂的软件层Flash Translation LayerFTL)。其实就是这个FTL才是SSD固态硬盘的软件核心技术。正因为有了FTLNAND Flash才能被当成硬盘来使用;文件系统才可以直接把SSD当成普通块设备来使用。由于FTLSSD设计厂商最为重要的核心技术,因此,没有一家厂商愿意透露这方面的技术信息,并且也一直没有业内的技术规范、标准存在。

FTL的重要程度在于决定了一个SSD的使用寿命、性能和可靠性。一旦FTL出现问题,那么就会导致数据读写发生错误,更为严重的是SSD盘无法被访问。优秀的FTL不仅能够提升Flash存储的使用寿命,而且还可以最优化读写性能。因此,在Flash固态存储中,FTL是一个最为重要的管理NAND Flash的软件层。

在学术界,这十年来有很多文章在讨论如果实现一个高效的FTL,例如,在有限硬件资源的环境下如何实现mapping?如何实现buffer的管理?如何实现高效的Garbage Collection?如何实现磨损均衡Wear-leveling?如何实现NAND Flash芯片之间的数据冗余(RAID on Chip)?很多算法的提出非常具有建设性和现实意义,对工业界具有很好的指导价值。

这里主要想谈一下FTL内部mapping的机制。从文章《采用NAND Flash设计存储设备的挑战在哪里?》了解到基于NAND Flash研制存储设备是有很多挑战的,最大的问题在于NAND Flash不能像内存那样随意的写入。NAND FlashPage页写入之前必须要将Page页所在的Block块擦除。如果研制SSD的时候严格按照这个准则,那么设计开发出来的SSD是不能用的。其一,按照这种方式进行写操作,写入的性能将会很差,其bottleneck限制在块擦除上(块擦除时间在ms级);其二,不断的对同一Block块进行擦除操作,那么该块将会在短时间内磨损写坏,并且极易导致存储在该块上的数据丢失。因此,在设计SSD时最主要的任务就是解决NAND Flash的这种“写时擦除”问题。

技术是相通的,在90年代提出的Log-structured File SystemLFS)思想和NAND Flash简直是天生一对。当初设计Log-Structured File System最主要的想法是利用机械磁盘出色的顺序写性能,避免糟糕的随机写问题。Log-structured File System在机械硬盘的时代有一定的应用局限性,问题在于采用log数据布局的方式之后,读性能变得很差。因此,只有在大块数据读写(对象存储)的环境下,log-structured File System才变得合情合理。在NAND Flash介质上,不存在机械硬盘随机读写的问题,因此,log-structured的数据布局方式不会引入任何性能问题,反而能够解决NAND Flash的“写时擦除”问题。

采用Log-structured的方式之后,NAND Flash可以采用out-of-place的数据更新方式。所有的数据更新都不会写入原来的page页,而是重映射写入一个新的Page页。在这个思路的引导,很显然所有NAND Flash的存储资源可以按照物理Page页的方式管理起来,而用户可见的空间则是一个连续逻辑Page页连接起来的地址空间。FTL的一个关键任务就是建立逻辑Page和物理Page之间的映射关系,并且在数据写入时重新分配物理Page页。在这种机制的支撑下,SSD的写性能可以大为提高,写延迟可以控制在200us的级别。

引入log-structured的机制之后,逻辑page和物理page之间存在映射关系,FTL负责物理page页的分配。考虑到每个Block块都是有擦除寿命的,因此,如果想要提升SSD的整体使用寿命,那么需要将块擦除次数均衡到所有块上去。这个工作就交给了FTL中的块分配器。均衡擦除次数这个工作其实是挺麻烦的事情,其最大的挑战在于记录每个块的擦写次数,并且这些信息需要持久化存储。

众所周知,log-structured数据布局方式最大的问题在于垃圾回收(garbage collection),由于page页从来不会被in-place-update,因此,当一个page被重映射之后,老的page页就会变成无效,等待Garbage Collection回收该页。在NAND Flash中,GC最大的挑战在于以块为单元进行擦除,而不是Page页。换句话说,GC需要将一个Block块中的所有Page页同时回收,这个限制导致GC在回收一个Block的时候会进行数据迁移操作。过多的数据迁移操作会影响SSD的使用寿命,并且会影响到整体的读写性能。因此,优化Garbage Collection成了FTL最头疼的一个问题。最容易想到的一个优化方法是将冷热数据分开存储到不同的Block块中,这样在数据回收的时候,可以尽最大可能减少有效数据的迁移。

Log-structured File SystemNAND FlashFTL设计提供了一个非常好的思路。但是,要想在SSD这样一个硬件资源非常有限的平台上实现FTL的所有功能还是很有挑战的。举个例子,log-structured的方式是需要进行Page页映射的,映射操作需要建立映射表。如果内存太小,那么对映射表的大小就提出了需求。假设一个SSD具有1TB的容量,那么如果采用4KB Page映射的方式,每个page映射需要4字节描述,那么至少需要1GB的内存容量来存放映射表。在嵌入式系统中,1GB的内存容量是庞大的。因此,为了避免过多的占用内存容量,拍脑袋可以想到Block映射的方式。假设一个Block容纳128Page页,那么一下子可以将映射表容量缩减到原来的1/128。但是这种Block映射的方式效率实在太低,会导致大量的数据迁移,从而缩短了SSD的使用寿命。所以,为了减小映射表的容量,一个比较可行的方式是采用Hybrid映射方式。

Hybrid-level mapping的思想是将映射操作分成两级。第一级是data-log,所有数据首先写入log,当log写满之后,再将log中的数据合并至data-block;第二级是data-block,用来存放从log中合并过来的数据。对于data-log,由于数量有限,因此可以采用page-level mapping的方式;对于data-block,由于存储容量比较大,因此,可以采用block-level mapping的方式。Hybrid-level mapping可以很好的平衡内存使用和mapping效率之间关系,因此,学术界也对此提出了很多优化的方法。

 

wKiom1OfBEji-swLAAEWz_4dq3Y721.jpg

 

其中,一个比较有意思的方法是locality awarehybrid-level mapping思想,其原理如上图所示。从结构上讲,其大致可以分成传统Hybrid-level mapping的双层结构。写入的数据首先进入data-log。不同的地方是,data-log被分成了random-log-buffersequential-log-buffer。写入的数据根据locality-detector被分流至random-log-buffer或者sequential-log-buffer。其中random-log-buffer采用page页映射的方式,sequential-log-buffer直接采用block映射的方法,这样可以进一步降低内存使用量。当log-buffer中的数据满了之后,需要合并到data-block。合并的方法和传统的相同,被分成switchpartial-mergefull-merge

FTLNAND Flash存储的底层核心技术之一,由于NAND Flash本身存在很多问题,导致FTL的设计、实现都会存在很多的挑战。上面只是简单的阐述了一下FTLmapping的一些棘手问题和一些解决思路,抛砖引玉,揭开了神秘面纱,往里面瞅上了一眼。这一看其实会发现,FTL虽小,但是难度丝毫不比一个文件系统小。