存储技术 -- SSD原理简介

最近开始读《深入浅出SSD-固态存储核心技术》等相关存储原理的书籍,本文是根据书内容所做的总结,解答了博主多年以来对存储方面的疑惑,希望本文对你有帮助。

SSD物理结构

SSD (Solid State Drive):即固态硬盘,是一种以半导体(NAND Flash)为介质的存储设备。从物理结构上来看,有以下几个组件:

  • 接口:用于与计算机等设备相连
  • 主控:本质上也是一颗小型CPU,负责数据读取,写入以及SSD自身维护等
  • 缓存DRAM:用于一些加速场景,比如映射表缓存 
  • 闪存:实际数据存储区域
  • PCB(电源,电容等):电源管理

因此可以大致想象整个工作方式如下图所示:主机通过接口将数据提交到SSD,SSD主控首先决定数据到底存储在闪存的什么位置,然后再将数据写入到具体的闪存位置中。

image-20210504213628535

SSD使用的闪存芯片其内部由许许多多存储单元构成,每一个存储单元是浮栅晶体管结构,对于该结构我们只需要知道其可以存储电子,且断电后电子不会消失,也因此SSD为非易失性存储器。从数据的角度,所谓的写数据,是控制电子数量来标识状态,读数据则是加电压,获取对应的状态。随着SSD不断的发展,一个存储单元能够标识的bit位数据在不断增加,将SSD颗粒分为SLC,MLC,TLC,QLC,分别对应1bit,2bit,3bit,4bit,其速度以及寿命随着bit位数增加而减少,但容量不断增大,当然成本也在逐渐降低,时至今日,SSD已经很接近与HDD的价格了。

image-20210504221045333

那么如何理解这发展现象?举个例子,当一个存储单元只需要表示1bit位数时,可以很简单的认为电子数大于0,标识1,小于等于0标识0,那么无论是加电压判断还是清空电子逻辑都方便很多。当需要表示2bit时,可以认为当电子数>=3时,为11,3>电子数>=2时标识10,2>电子数>=1时标识01,电子数为0时标识0,那么要准确判断数据到底是什么自然就麻烦了很多,因此随着bit表示增加,实际情况只会更加复杂,因此性能是逐渐下降的。

但随之带来的好处是成本的下降,在1bit存储单元时代,大容量的SSD只能依赖工艺的提升,在一个闪存芯片中塞入更多的存储单元,但带来的容量却很有限,然而牺牲部分速度前提下,一个存储单元标识2bit,相同面积下容量直接翻倍,这是SSD能够普及消费者市场的重要推力。

SSD数据存储结构

大容量的SSD,一般由多个NAND Flash所组成,这里单独看一个NAND Flash。

最外层被称为DIE/LUN,该部分是接收与执行闪存命令的基本单元,一个LUN又由多个Plane所构成,Plane是真正执行数据读写单元,因此具备独立的Cache Register以及Page Register,一个Plane由多个Block所构成,Block是数据擦除的基本单位,由于擦除需要较高电压,因此在Block层面是比较妥协的做法,Block由多个Page构成,一个Page一般4KB,Page是最基本的数据读写单位。这里直接借用书中的图,能够很清晰的展示上述关系。

image-20210505000759287

读写流程

先不考虑操作系统的影响,当主控接收到读写命令后,会将其下发到对应的LUN,LUN再下发到Plane上。正常情况下读写流程只需要Cache Register参与即可。举个例子,写入时,数据先写到Cache Register,然后再由Cache Register写入到闪存介质中,读取时,数据先读取到Cache Register,然后再传输到主控,这里的读写单位都是Page。

那么Page Register有什么用?闪存除了上述正常读写流程外,还支持Cache读写,在Cache读情况下,当主控读取Cache Register时,Page Register可以开始读取下一份数据,也就是预读,从而减少等待时间。同理,Cache写情况下当一份数据正在写入时,主控可以将另一份数据传输到Cache Register中。这里博主是类比计算机设计,一个SSD看作是小型计算机系统,主控作为CPU属于高速设备,存储介质自然是低速设备,两者之间速度不匹配带来了巨大的CPU性能损耗,因此Cache Register以及Page Register承担的是寄存器的作用,尽可能降低这种速度不匹配带来的影响。

image-20210505102331283

Block有什么用

上述读写流程中,并没有出现Block这一结构,那么为什么需要Block?

在SSD中,由于NAND Flash的特性,每次写入都是以Page维度,并且只能写入到空闲的Page,无法覆写原本有内容的Page,因此产生了擦除。由于擦除本身需要高电压,让电子转移,也因此Block的存在是为了应对数据擦除,对于SSD来说数据的擦除是在对应存储单元上加高电压,经过足够长的时间后,电子会丢失,整个存储单元回到初始状态。

SSD核心:FTL

可以认为Block是SSD的基本管理单位,由于闪存块的寿命限制,整个Block的管理算法并没有想象中那么简单,常见的有以下几个问题:

  • 由于Page不能覆写,当数据发生变更时,必须写入到一个新的位置,那么必须需要映射表存在。旧位置的数据此时成为了垃圾数据,那么必须需要GC来进行垃圾回收。
  • 闪存块都是有具体寿命的,因此要保证SSD的整体寿命以及性能,需要均衡每个闪存块的擦除次数,保证整体使用寿命,这叫磨损平衡。
  • 闪存块读取存在次数限制,读的太多了,上面数据会出错,造成读干扰,因此在读取一定次数后,需要将数据搬迁到新的块当中。同样,如果长时间不读,那么电子也会流失,造成数据错乱,闪存块也需要搬动数据来提高数据准确性。这也是SSD断电不使用容易丢失数据的本质原因。

上述问题的解决全靠FTL (Flash Translation Layer),FTL最基础的功能是将主机的逻辑地址空间翻译成闪存的物理地址空间,除此之外好的FTL还会实现上述的垃圾回收,磨损平衡,坏块管理,数据保持等问题。

页映射

操作系统访问SSD时,是通过LBA(Logical Block Address)进行寻址,LBA的大小由具体的文件系统所决定,一般为4KB。SSD内部维护了一个逻辑页到物理页的映射关系表,用户每写入一个逻辑页,就会产生一条新的映射关系。

SSD会在内部开辟一个单独的空间用于存储映射表,以256G大小的SSD,映射表大概256MB,SSD板载的DRAM其主要目地是为了缓存该映射表,这样,映射关系的查找就会变得非常迅速,从而提高整个SSD的访问效率。

image-20210505114449143

垃圾回收

由于闪存无法覆盖写,那么数据变更时,变更部分会直接写入到新的区域。FTL会控制一个块上垃圾页的比例,垃圾页大于一定阈值时,触发垃圾回收,主要流程是将正常页搬迁到其他块,然后对整个块进行擦除达到回收目地。如下图所示,回收到x,y两个块的可用数据迁移到z,同时擦除x,y。

image-20210505140231494

这里额外提下Trim指令,Trim是SSD提供的指令,用于主机上删除文件时,主动通知SSD对应文件已经被删除,这样可以方便对SSD做垃圾回收,而不是写入时才垃圾回收。按理来说这个是本来就该有的指令,为什么单独提起呢?我想大概原因还是SSD近些年才开始大范围普及,早起的HDD是支持覆写的,不需要垃圾回收,操作系统给定指令直接写即可,而SSD需要擦除后才能写,因此多了这一步骤。现在的SSD基本都默认开启了trim,我们也无需太关注这个。

磨损平衡

每个闪存块的寿命有限,想要保证SSD最佳寿命,即需要保证每个闪存块的擦除数保持平衡。从数据的更新频次来看,主要有冷数据以及热数据,比如操作系统的很多文件,写入后基本不再更新。而日常应用日志却更新频繁。那么FTL需要将冷的数据搬迁到写入次数比较多的闪存块,这叫静态磨损平衡。此外FTL还需要将热数据写到磨损次数比较少的块上,这叫动态磨损平衡。

数据保持

数据保持主要解决两个问题,其一是读次数限制,读次数主要因为读取时是加一定电压,相当于轻微写入,次数多了自然会造成数据不准确,FTL的做法很简单,针对读大于一定次数的块,主动搬迁数据到新的块,然后擦除该块。其二是电子自然流失导致数据不准确,FTL则会每隔一段时间对块进行扫描,发现其中bit翻转大于一定阈值,则主动进行搬迁刷新数据。

总结

整个SSD设计还有很多其他的问题需要处理,本文根据书籍内容只是做了一些简单总结,有兴趣的建议看参考中的书籍,写的很详细,值得阅读。

另外一块单独的SSD我们可以理解是一块未被开垦的荒地,想要实际存储数据还需要搭配文件系统+操作系统,这部分内容后续文章会分析总结,敬请期待。

参考

《深入浅出SSD-固态存储核心技术》- SSDFans

造轮子--Command Search Alfred
读书笔记 -- 《Maven实战》