我们都知道,早期的电脑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):
两篇关于硬盘的文章是否让你对硬盘的结构和工作原理有了一定的了解呢?如果你正在学java,你会发现java虚拟机jvm,它的工作原理,就是参考的硬件的实际工作原理哦!