SSD固态硬盘的结构和基本工作原理概述
我们都知道,早期的电脑CPU是可以直接从硬盘上面读取数据进行处理的,随着科技的进步,时代的发展,计算机硬件的发展速度也是极其迅猛。CPU主频的不断提升,从单核到双核,再到多核;CPU的处理速度越来越快,而硬盘的的读写速度已经远远跟不上CPU的读写速度,后来增加了内存这个读写速度相对较快的缓存,而内存也是蓬勃到发展,从SDRAM到DDR,从DDR到DDR2再到DDR3,但是无论怎样,内存缓存速度还是跟不上CPU的运算处理速度,后来便在CPU中增加了快速缓存机制!而硬盘这个持久化存储器呢?之前的文章,聊到了机械硬盘的结构和工作原理,今天就来聊一聊SSD固态硬盘的结构和基本工作原理,如理解有所变差,或文章有所不足,皆因水平所限!
硬盘的发展在不断的科技进步中快速提升,从容量以及速度再到接口方面。从早期的PATA变成SATA,SCSI变到SAS,以及垂直记录技术在容量上的突破,但这些进步亦未能改变磁盘的记录方式。随着人们对数据需求增多,存储系统的瓶颈越来越明显。而在嵌入式领域移动设备和工业自动化控制等恶劣环境下,传统硬盘机械结构已经无法满足要求,而所有这一切随着固态存储(SSD)的到来而发生了改变。
传统的机械硬盘(HDD)运行主要是靠机械驱动头,包括马达、盘片、磁头摇臂等必需的机械部件,它必须在快速旋转的磁盘上移动至访问位置,至少95%的时间都消耗在机械部件的动作上。SSD却不同机械构造,无需移动的部件,主要由主控与闪存芯片组成的SSD可以以更快速度和准确性访问驱动器到任何位置。传统机械硬盘必须得依靠主轴主机、磁头和磁头臂来找到位置,而SSD用集成的电路代替了物理旋转磁盘,访问数据的时间及延迟远远超过了机械硬盘。SSD有如此的“神速”,完全得益于内部的组成部件:主控--闪存--固件算法。
主控、闪存及固件算法三者的关系:
SSD最重要的三个组件就是NAND闪存,控制器及固件。NAND闪存负责重要的存储任务,控制器和固件需要协作来完成复杂且同样重要的任务,即管理数据存储、维护SSD性能和使用寿命等。
主控:
控制器是一种嵌入式微芯片(如电脑中CPU),其功能就像命令中心,发出SSD的所有操作请求----从实际读取和写入数据到执行垃圾回收和耗损均衡算法等,以保证SSD的速度及整洁度,可以说主控是SSD的大脑中枢。目前主流的控制器有Marvell、SandForce、Samsung、Indilinx等。像Marvell各方面都很强劲,代表型号为Marvell 88SS9187/89/90主控,运用在浦科特、闪迪、英睿达等品牌的SSD上。
SandForce的性能也不错,它的特点是支持压缩数据,比如一个10M的可压缩数据可能被他压成5M的写入硬盘,但还是占用10M的空间,可以提高点速度,最大的特点是会延长SSD的寿命,但是CPU占用会高点而且速度会随着硬盘的使用逐渐小幅度降低。代表型号为SF-2281,运用在包括Intel、金士顿、威刚等品牌的SSD上。
Samsung主控一般只有自家的SSD上使用,性能上也是很强悍的,不会比Marvell差多少。目前三星主控已经发展到第五代MEX,主要运用在三星850EVO、850PRO上。
固件算法:
SSD的固件是确保SSD性能的最重要组件,用于驱动控制器。主控将使用SSD中固件算法中的控制程序,去执行自动信号处理,耗损平衡,错误校正码(ECC),坏块管理、垃圾回收算法、与主机设备(如电脑)通信,以及执行数据加密等任务。由于固件冗余存储至NAND闪存中,因此当SSD制造商发布一个更新时,需要手动更新固件来改进和扩大SSD的功能。
开发高品质的固件不仅需要精密的工程技术,而且需要在NAND闪存、控制器和其他SSD组件间实现完美整合。此外,还必须掌握NADN特征、半导体工艺和控制器特征等领域的最先进的技术。固件的品质越好,整个SSD就越精确,越高效,目前具备独立固件研发的SSD厂商并不多,仅有Intel/英睿达/浦科特/OCZ/三星等厂商,希望我国能早日解决。
NAND闪存:
SSD用户的数据全部存储于NAND闪存里,它是SSD的存储媒介。SSD最主要的成本就集中在NAND闪存上。NAND闪存不仅决定了SSD的使用寿命,而且对SSD的性能影响也非常大。NAND闪存颗粒结构及工作原理都很复杂,接下来我们会继续推出系列文章来重点介绍闪存,这里主要来了解一下大家平常选购SSD经常接触到的SLC、MLC及TLC闪存。
SLC/MLC/TLC闪存:
三种闪存状态
这几年NAND闪存的技术发展迅猛同,从企业级标准的SLC闪存到被广泛运用在消费级SSD上的MLC闪存再到目前正在兴起的TLC闪存,短短时间里,我们看到NAND技术显著进步。对SLC、MLC及TLC闪存怎么理解呢?简单来说,NAND闪存中存储的数据是以电荷的方式存储在每个NAND存储单元内的,SLC、MLC及TLC就是存储的位数不同。
单层存储与多层存储的区别在于每个NAND存储单元一次所能存储的“位元数”。SLC(Single-Level Cell)单层式存储每个存储单元仅能储存1bit数据,同样,MLC(Multi-Level Cell)可储存2bit数据,TLC(Trinary-Level)可储存3bit数据。一个存储单元上,一次存储的位数越多,该单元拥有的容量就越大,这样能节约闪存的成本,提高NAND的生产量。但随之而来的是,向每个单元存储单元中加入更多的数据会使得状态难以辨别,并且可靠性、耐用性和性能都 会降低。
一颗NAND芯片是32G的容量,也就是说128G的SSD,内部是5个NAND芯片做并行读取。读写的时候都依靠主控芯片来做控制,主控芯片还要对所有的NAND闪存芯片做磨损平衡,保证这帮兄弟要挂一起挂,假如是256G的,内部是8通道,并发的读写能力比128G会有了接近50%的提升。至于再大的容量,因为存储容量过大,导致主控芯片保存的地址映射表过大,性能可能会出现持平甚至下降的情况。
固态硬盘是无需移动的固态电子元件,可以直接进行数据读取。具体量化的概念就是,一台笔记本电脑在使用传统硬盘时可能需要等待36秒才能让操作系统完成启动,而现在如果使用固态硬盘,则只需等待不到9秒钟。基于这种高性能硬盘的协同工作,CPU的运行效率也会提高,其节省能耗的优点足以使电池延长15%的寿命,而且它更加抗震和轻便。而传统硬盘在读取及写入数据的时候,硬盘磁头需要花费时间转动并找到数据所在的位置。
工作原理概述
SSD主控通过若干个通道(channel)并行操作多块FLASH颗粒,类似RAID0,大大提高底层的带宽。举个例子,假设主控与FLASH颗粒之间有8个通道,每个通道上挂载了一个闪存颗粒,HOST与FLASH之间数据传输速率为200MB/s。该闪存颗粒Page大小为8KB,FLASH page的读取时间为Tr=50us,平均写入时间为Tp=800us,8KB数据传输时间为Tx=40us。那么底层读取最大带宽为(8KB/(50us+40us))*8 = 711MB/s,写入最大带宽为(8KB/(800us+40us))*8 = 76MB/s。从上可以看出,要提高底层带宽,可以增加底层并行的颗粒数目,也可以选择速度快的FLASH颗粒(或者让速度慢的颗粒变快,比如MLC配成SLC使用)。主控通过8通道连接8个FLASH DIE,为方便解释,这里只画了每个DIE里的一个Block,其中每个小方块表示一个Page (假设大小为4KB)。
HOST写入4KB数据
HOST继续写入16KB数据
HOST继续写入,最后整个Block都写满
当所有Channel上的Block都写满的时候,SSD主控会挑选下一个Block以同样的方式继续写入。
HOST是通过LBA(Logical Block Address,逻辑地址块)访问SSD的,每个LBA代表着一个Sector(一般为512B大小),操作系统一般以4K为单位访问SSD,我们把HOST访问SSD的基本单元叫用户页(Host Page)。而在SSD内部,SSD主控与FLASH之间是FLASH Page为基本单元访问FLASH的,我们称FLASH Page为物理页(Physical Page)。HOST每写入一个Host Page, SSD主控会找一个Physical Page把Host数据写入,SSD内部同时记录了这样一条映射(Map)。有了这样一个映射关系后,下次HOST需要读某个Host Page 时,SSD就知道从FLASH的哪个位置把数据读取上来。
SSD内部维护了一张映射表(Map Table),HOST每写入一个Host Page,就会产生一个新的映射关系,这个映射关系会加入(第一次写)或者更改(覆盖写)Map Table;当读取某个HostPage时, SSD首先查找Map Table中该Host Page对应的Physical Page,然后再访问Flash读取相应的Host数据。
一张Map Table有多大呢?这里假设我们有一个256GB的SSD,以4KB Host Page为例,那么一共有约 64M(256GB/4KB)个Host Page,也就意味着SSD需要有64M大小的Map Table。Map Table中的每个Entry存储的就是物理地址(Physical Page Address),假设其为4Byte (32bits) ,那么整个Map Table的大小为64M*4B = 256MB。对绝大多数SSD,我们可以看到上面都有板载DRAM,其主要作用就是用来存储这张映射表。也有例外,比如基于Sandforce主控的SSD,它并不支持板载DRAM,那么它的映射表存在哪里呢?SSD工作时,它的绝大部分映射是存储在FLASH里面,还有一部分存储在片上RAM上。当HOST需要读取一些数据时,对有板载DRAM的SSD来说,只要查找DRAM当中的映射表,获取到物理地址后访问FLASH从而得到HOST数据.这期间只需要访问一次FLASH;而对Sandforce的SSD来说,它首先看看该Host Page对应的映射关系是否在RAM内,如果在,那好办,直接根据映射关系读取FLASH;如果该映射关系不在RAM内,那么它首先需要把映射关系从FLASH里面读取出来,然后再根据这个映射关系读取Host数据,这就意味着相比有DRAM的SSD,它需要读取两次FLASH才能把HOST数据读取出来,底层有效带宽减半。对HOST随机读来说,由于片上RAM有限,映射关系Cache命中(映射关系在片上RAM)的概率很小,所以对它来说,基本每次读都需要访问两次FLASH,所以我们可以看到基于Sandforce主控的SSD随机读取性能是不太理想的。继续回到之前的SSD写操作。当整个SSD写满后,从用户角度来看,如果想写入新的数据,则必须删除一些数据,然后腾出空间再写。用户在删除和写入数据的过程中,会导致一些Block里面的数据变无效或者变老。如下图所示(绿色小方块代表有效数据,红色小方块代表无效数据):
Block中的数据变老或者无效,是指没有任何映射关系指向它们,用户不会访问到这些FLASH空间,它们被新的映射关系所取代。比如有一个Host Page A,开始它存储在FLASH空间的X,映射关系为A->X。后来,HOST重写了该Host Page,由于FLASH不能覆盖写,SSD内部必须寻找一个没有写过的位置写入新的数据,假设为Y,这个时候新的映射关系建立:A->Y,之前的映射关系解除,位置X上的数据变老失效,我们把这些数据叫垃圾数据。随着HOST的持续写入,FLASH存储空间慢慢变小,直到耗尽。如果不及时清除这些垃圾数据,HOST就无法写入。SSD内部都有垃圾回收机制,它的基本原理是把几个Block中的有效数据(非垃圾数据,上图中的绿色小方块表示的)集中搬到一个新的Block上面去,然后再把这几个Block擦除掉,这样就产生新的可用Block了。
上图中,Block x上面有效数据为A,B,C,Block y上面有效数据为D,E,F,G,红色方块为无效数据。垃圾回收机制就是先找一个未写过的可用Block z,然后把Block x和Block y的有效数据搬移到Block z上面去,这样Block x和Block y上面就没有任何有效数据,可以擦除变成两个可用的Block。
一块刚买的SSD,你会发现写入速度很快,那是因为一开始总能找到可用的Block来进行写入。但是,随着你对SSD的使用,你会发现它会变慢。原因就在于SSD写满后,当你需要写入新的数据,往往需要做上述的垃圾回收:把若干个Block上面的有效数据搬移到某个Block,然后擦掉原先的Block,然后再把你的Host数据写入。这比最初单纯的找个可用的Block来写耗时多了,所以速度变慢也就可以理解了。
还是以上图为例。假设HOST要写入4KB数据 (H) ,由于当前可用Block过少,SSD开始做垃圾回收。从上图可以看出,对Block x来说,它需要把Page A,B,C的数据读出并写入到Block z,然后Block x擦除用于HOST数据写入。从Host角度,它只写了4KB数据,但从SSD内部来说,它实际写入了4个Page(Page A, B, C写入Block z,4KB数据H写入到Block x)。
垃圾回收原理
再看一下这张图。回收Block x,上面有3个有效Page,需要读写3个Page完成整个Block的回收;而回收Block y时,则需要读写4个有效Page。两者相比,显然回收Block x比回收Block y快一些。说明一个简单的道理:一个Block上有效的数据越少(垃圾数据越多),则回收速度越快。
256GB FLASH配成256GB的SSD (OP = 7.37%), 意味着256*10^9的有效数据写到 256*2^30的空间,每个Block上面的平均有效数据率可以认为是256*10^9/256*2^30 = 93.1%。
如果配成240GB的SSD,则意味着240*10^9的有效数据写到256*2^30的空间,每个Block的平均有效数据率为240*10^9/256*2^30 = 87.3%。
OP越大,每个Block平均有效数据率越小,因此我们可以得出的结论:OP越大,垃圾回收越快,写放大越小。这就是OP大的好处。
写放大越小,意味着写入同样多的HOST数据,写入到FLASH中的数据越少,也就意味着FLASH损耗越小。FLASH都是有一定寿命的,它是用P/E数 (Program/Erase Count)来衡量的。(关于FLASH基础知识,请参考《闪存基础》)。如果SSD集中对某几个Block进行擦写,那么这几个Block很快就寿命耗尽。比如在用户空间,有些数据是频繁需要更新的,那么这些数据所在Block就需要频繁的进行擦写,这些Block的寿命就可能很快的耗尽。相反,有些数据用户是很少更新的,比如一些只读文件,那么这些数据所在的Block擦写的次数就很少。随着用户对SSD的使用,就会形成一些Block有很高的PE数,而有些Block的PE数却很低的。这不是我们想看到的,我们希望所有Block的PE数都应该差不多,就是这些Block被均衡的使用。在SSD内部,有一种叫磨损平衡(Wear Leveling,WL)的机制来保证这点。
WL有两种算法:动态WL和静态WL。所谓动态WL,就是在使用Block进行擦写操作的时候,优先挑选PE 数低的;所谓静态WL,就是把长期没有修改的老数据(如前面提到的只读文件数据)从PE数低的Block当中搬出来,然后找个PE 数高的Block进行存放,这样,之前低PE数的Block就能拿出来使用。
下面这张图(来源网络)诠释了无WL,动态WL和静态WL下的FLASH耐久度的区别 (假设每个Block最大PE数为10,000):