神秘的Flash Translation Layer (FTL)

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

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 Flash Page 页写入之前必须要将 Page 页所在的 Block 块擦除。如果研制 SSD 的时候严格按照这个准则,那么设计开发出来的 SSD 是不能用的。其一,按照这种方式进行写操作,写入的性能将会很差,其 bottleneck 限制在块擦除上(块擦除时间在 ms 级);其二,不断的对同一 Block 块进行擦除操作,那么该块将会在短时间内磨损写坏,并且极易导致存储在该块上的数据丢失。因此,在设计 SSD 时最主要的任务就是解决 NAND Flash 的这种“写时擦除”问题。

技术是相通的,在 90 年代提出的 Log-structured File System LFS )思想和 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 System NAND Flash FTL 设计提供了一个非常好的思路。但是,要想在 SSD 这样一个硬件资源非常有限的平台上实现 FTL 的所有功能还是很有挑战的。举个例子, log-structured 的方式是需要进行 Page 页映射的,映射操作需要建立映射表。如果内存太小,那么对映射表的大小就提出了需求。假设一个 SSD 具有 1TB 的容量,那么如果采用 4KB Page 映射的方式,每个 page 映射需要 4 字节描述,那么至少需要 1GB 的内存容量来存放映射表。在嵌入式系统中, 1GB 的内存容量是庞大的。因此,为了避免过多的占用内存容量,拍脑袋可以想到 Block 映射的方式。假设一个 Block 容纳 128 Page 页,那么一下子可以将映射表容量缩减到原来的 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 aware hybrid-level mapping 思想,其原理如上图所示。从结构上讲,其大致可以分成传统 Hybrid-level mapping 的双层结构。写入的数据首先进入 data-log 。不同的地方是, data-log 被分成了 random-log-buffer sequential-log-buffer 。写入的数据根据 locality-detector 被分流至 random-log-buffer 或者 sequential-log-buffer 。其中 random-log-buffer 采用 page 页映射的方式, sequential-log-buffer 直接采用 block 映射的方法,这样可以进一步降低内存使用量。当 log-buffer 中的数据满了之后,需要合并到 data-block 。合并的方法和传统的相同,被分成 switch partial-merge full-merge

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

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章