Skip to main content
  1. Posts/

Coding for SSDs - Part 6: A Summary – What every programmer should know about solid-state drives

·1 min·
存储 SSD
Tech Enthusiast running out of Coffee.
Table of Contents

在这部分,我以独立的简单段落的形式总结了其它部分的内容。每个段落概括了其他部分一节或几节的内容,这样可以让读者在每个主题下能够得到更多细节。

基础
#

1.存储单元类型
#

固态硬盘(SSD)是基于闪存的数据存储设备。每个比特都存储在存储单元中,而存储单元分为三类:每个单元1比特(单层单元,SLC),每个单元2比特(多层单元,MLC),每个单元3比特(三层单元,TLC)。

详见第1.1节

2.寿命限制
#

每个单元都有P/E(写/擦)循环的最大限制,在此之后存储单元被认为是损坏的。这表示NAND闪存已经损耗殆尽,并有一个寿命限制。

详见第1.1节

3.基准测试很难
#

测试者是人,因此并不是所有的基准测试都毫无破绽。在读生产商或者第三方的基准测试结果的时候请小心,并在相信这些数据之前使用多个来源的数据。在有可能的时候,使用你的系统特定的工作负载在你打算使用的SSD型号上,运行自己的内部基准测试。最后,着眼于与你的系统最相关的性能指标。

详见第2.2节和第2.3节

页和块
#

4.NAND闪存页和块
#

闪存单元组织成为阵列,称为块,而块组织成为面。块中能够进行读写操作的最小单元是页。页不能独立擦除,只能整块擦除。NAND闪存页大的大小并不一致,大多数硬盘的页大小是2KB、4KB、8 KB 或16 KB。大多数SSD每个块有128或256个页。这即表示一个块的大小可能在256 KB 到4 MB之间。例如Samsung SSD 840 EVO的块大小是2048 KB,每块包括256页每页8KB。 详见第3.2节

5.读是页对齐的
#

一次读取少于一页是不可能的。当然可以通过操作系统只请求一个直接,但SSD中会取回整个页,强制读取比所需多的多的数据。 详见第3.2节

6.写是页对齐的
#

写入到SSD的时候,写入将补齐到页大小。所以即便写入操作只影响一字节,都会重写整个页。写入比所需更多的数据被称为写入放大。写入一个页也被称为“(编置to program)”一个页。

详见第3.2节

7.页不能覆写
#

NAND闪存页只能在其为“空”的状态下进行写入。当数据改变,页的内容被复制到内部寄存器中,数据更新,然后新版本的数据将存储字啊一个”空“页中,这个操作被称为”读-改-写“。数据并非原地更新,因为”空”页并非原先存储数据的页。一旦数据被保存到硬盘上,原来的页将被标记为“废弃”,并一直保持这样直到被擦除。 详见第3.2节

8.擦除是块对齐的
#

页不能被覆写,一旦页成为“废弃的”,让其重新空下来的方法是擦除它们。然而,独立擦除一个页是不可能的,并且只能一次擦除整个块。

详见第3.2节

主控和内部
#

9.闪存转换层
#

闪存转换层(FTL)是SSD主控中的一个组件,它将来自主机的逻辑块地址(LBA)映射为硬盘上的物理块地址(PBA)。很多最新的硬盘使用了类似于“混合日志块”或其派生者的技术,其以类似于日志结构文件系统的方式工作。这允许将随机写入当做顺序写入处理。 详见第4.2节

10.内部并行
#

在内部,数个层次的并行使得可以一次向不同NAND闪存芯片上写数个块的数据,这几个块被称为“簇”。 详见第6节

11.损耗均衡
#

因为NAND闪存单元会损耗殆尽,FTL的一个主要目标是额能的将工作分散到各个单元上,这样块中的闪存单元可以在同一时间损坏。

详见第3.4节

12.垃圾回收
#

SSD主控中的垃圾回收确保废弃的块能够擦除并重新变为空状态,使新进入的写入命令可以访问。

详见第4.4节 (译注:你没看错,少了13,原文就是这样)

14.后台操作可能影响前台操作
#

例如垃圾回收的后台操作可能对来自主机的前台操作有负面影响,尤其是在持续的小随机写入工作负载下。 详见第4.4节 访问模式 15.绝不写入少于一页的数据


避免写入少于NAND闪存页大小的数据以最小化写入放大并避免读-改-写操作。目前一页最大为16KB,因此此值应该作为默认值使用。这个值取决于SSD型号,并且在将来SSD改进之后你可能需要增加。

详见第3.2和3.2节

16.对齐写入
#

将写入对齐为页大小,写入数据块大小为页大小的倍数。 详见第3.2和3.2节

17.小写入缓存化
#

为了最大化吞吐量,在任何可能的时候将小写入缓存到内存中,当缓存满了再进行一次大写入,这样来将小写入打包。

详见第3.2和3.2节

18.为了提升读性能,将相关的数据写在一起。
#

读取性能取决于写入模式。当大数据块一次写入的时候,其将被分配到不同的NAND闪存芯片上。因此你需要将相关的数据写到相同的页、块、或簇上,这样在你之后读取的时候可以利用内部并行,用一个I/O请求更快的读取。

详见7.3节

19.分离读写请求
#

混合的小读写交叉的工作负载会妨碍内部缓存和预读取机制正常工作,并会导致吞吐量下降。最好的办法是避免同时发生的读操作和写操作,并将其以一个接一个的大数据块的形式实现,数据块大小推荐和簇大小相同。举个例子,如果要更新1000个文件,你可以遍历文件逐一读写,但会很慢。如果一次读取1000个文件然后一次写回1000个文件将会好很多。 详见7.4节 20.批量废弃数据


当有数据不再需要或者需要删除的时候,最好等到废弃数据量比较大的时候在一个操作中统一废弃它们。这可以使垃圾回收进程可以一次处理更大范围的数据,可以最小化内部碎片。

详见第4.4节

21.随机写入并不远总是比顺序写入慢
#

如果写入很小(即小于簇大小)。随机写入将比顺序写入慢。如果写入都是数倍于且对齐簇大小的话,随机写入将会利用所有可用层次的内部并行,并达到和顺序写入相同的水平。对于大部分硬盘来说,簇大小是16或32MB,因此使用32MB应该是安全的。

详见第7.2节

22.一个大的单线程的读取比很多小的并发读取要好
#

并发随机读取不能完全使用预读取机制。并且,多个逻辑块地址会指向同一个芯片而不能利用内部并行。一个大的书签操作将会访问连续地址并在预读取缓存可用的时候利用之,并使用内部并行。因此如果用例允许的话,发出一个大的读取请求会好一些。

详见第7.3节

23.一个大的单线程写入比很多小的并发写入要好
#

大的单线程写入请求提供的吞吐量和很多并发写入是相同的,然而就延迟来说,一个大的单一写入比并发写入反应时间要短一些。因此,在可用的时候,使用单线程大写入是最好的。

详见7.2节

24.当写入小且无法缓存或组织在一起的时候,多线程是有用的。
#

很多并发写入请求将比单一小写入请求提供的吞吐量要大。因此,如果I/O很小并且不能组织,用多线程比较好。

详见第7.2节

25.分离冷热数据
#

热数据是经常改变的数据,而冷数据是不经常改变的数据。如果一些热数据和冷数据被保存在同一个页中,冷数据将会随着热数据的每次读-改-写操作一起复制,并且会因为垃圾回收的损耗均衡不停移动位置。尽可能的将冷热数据分离到不同的也中将减轻垃圾回收的工作。

详见4.4节

26.缓存热数据
#

极其热的速进和其他高频变化的元数据应该尽可能的缓存并尽可能少的写入硬盘。

详见4.4节

系统优化
#

27.PCI Express 和SAS比SATA快
#

生产商提供的两个主要的接口是SATA 3.0 (550 MB/s) 和 PCI Express 3.0 (1 GB/s 每通道,使用多个通道)。串行SCSI(SAS)同样在企业级的SSD上可用。在最新版本中,PCI Express和SAS比SATA要快,但也更贵。

详见2.1节

28.预留空间对提高性能和损耗均衡十分有用
#

硬盘可以简单地通过在格式化的时候让逻辑分区容量比最大物理容量小来设置预留空间。预留的空间对用户不可见,但SSD主控仍然可见。预留空间帮助损耗均衡机制应付NAND闪存单元固有的寿命限制。对于写入负载不是很重的工作环境,10%~15%的预留空间足够了。对于持续随机写入的工作负载,保持25%的工作负载将会提升性能。预留空间将会扮演NAND闪存块的缓存的角色,帮助垃圾回收进程吸收写入峰值。

详见5.2节

29.启用TRIM命令
#

确认你的系统内核和文件系统支持TRIM命令。TRIM命令在块被删除的时候通知SSD主控。当垃圾回收进程能够在空闲时候后台擦除这些块,为将来的写入负载准备硬盘。 详见第5.1节

30.对齐分区
#

为了确保逻辑写入确实和物理存储设备对齐,你需要将分区和硬盘的NAND闪存页对齐。

详见第8.1节

总结
#

这是为“SSD编程”系列文章的总结。我希望我用易于理解的方法表述了我在固态硬盘上的个人研究中学到的东西。 如果你读了这个系列并想深入了解SSD,比较好的起步点是读一些我在第二部分和第五部分列出的引用文献和文章。 另外一个很好的学习资源是FAST大会(the USENIX Conference on File and Storage Technologies,USENIX文件和存储技术大会)。会上每年都有大量出色的研究。我高度推荐他们的网站, FAST 2013视频和文献的集散地。(译注:截至本文翻译完毕,  FAST 2014的网站已经可用了。)

Related

Coding for SSDs - Part 5: Access Patterns and System Optimizations
·2 mins
存储 SSD
Coding for SSDs – Part 4: Advanced Functionalities and Internal Parallelism
·1 min
存储 SSD
Coding for SSDs - Part 3: Pages, Blocks, and the Flash Translation Layer
·2 mins
存储 SSD
Coding for SSDs - Part 2: Architecture of an SSD and Benchmarking
·4 mins
存储 SSD