“没有一点点防备
也没有一丝顾虑
你就这样出现在我的世界里
带给我惊喜
情不自已”
不过,突如其来的掉电,对SSD来说,没有”喜”,只有”惊”。
SSD为什么怕掉电?它不是用Flash做存储介质吗?它不是Non-volatile吗?
没错。不过,一个SSD,除了Non-volatile的Flash,还需要Volatile的RAM,SRAM或者DRAM。Flash的作用是存储数据,而RAM主要是SSD工作时用以缓存用户数据和存放映射表 (逻辑地址映射闪存物理地址)。所以一旦掉电,RAM的数据就会丢失。
为防止异常掉电数据丢失,一个简单的设计就是在SSD上面放电容,SSD一旦检测到掉电,就让电容开始放电,然后把RAM中的数据Flush到Flash上面去,从而避免数据丢失。如下图SSD:
电容放电时间很短,要保证在有限时间内把RAM中数据Flush到Flash,RAM中数据量不能太多。
还有一个比较前卫的想法,就是把RAM这种Volatile的东西,用Non-Volatile的东西来替代,但要求这种Non-volatile的东西性能上接近RAM。这样,整个SSD都是Non-volatile的了,妈妈再也不用担心我的SSD异常掉电了。Intel和Micron不是说他们的3D XPOINT很牛吗,等我有钱了,我也搞个玩玩,就把RAM换成3D XPOINT。
RAM中缓存的用户数据,主机自认为把它们写到SSD了,但SSD只是把它们缓存在RAM中,并没有写到Flash。异常掉电时,如果SSD上没有使用电容,也没有使用其它黑科技,这部分数据是损失无疑。重上电时,主机是再也读不到这些数据了。
那么,是不是写到Flash上的用户数据,主机就一定能读取到呢?我们看看主机读SSD上数据的过程。首先,主机通过逻辑地址向SSD要数据,在SSD内部,需要利用这个逻辑地址作为索引,查找映射表获得用户数据在Flash上的物理地址,然后SSD再读Flash获得主机所需数据。(关于映射表这个东西,可以参看《SSD背后的秘密:SSD基本工作原理》)可以看出,映射表数据很重要,对一个逻辑地址,如果SSD查找不到对应的物理地址,它就无法从Flash上读取数据返回给主机;如果映射表中的数据不是最新的,旧的物理地址对应着老的数据,SSD就会错误的把老数据返回给主机。这个问题就严重了:小明原账户上有10块钱,最近存入100万,但由于异常掉电导致银行没有把100万写入到数据库,下次小明到ATM上一看,怎么还是10块钱,小明当时就昏死过去! (各位看官,我只是举个例子,诸位不要跟我较真,说银行系统不会这么傻逼之类。。。)。所以,如果映射表数据丢失,即使用户的数据存在Flash上,主机也无法获取。
标题是”SSD异常掉电数据恢复技术”,其中的”数据”,在本文中,准确来说就是SSD映射表。异常掉电时,RAM中缓存的用户数据没有办法挽回,但写入到Flash中的数据还是可以挽回的。SSD映射表恢复了,这部分数据自然就回来了。
那么,怎么重建映射表呢?
SSD在写用户数据到Flash的时候,会额外的打包一些数据,我们叫它元数据(Meta Data),它记录着该笔用户数据的相关信息,比如该笔数据对应的逻辑地址,数据长度,以及时间戳(数据写入到Flash的时间)等等。
Meta Data: | Logical Address | TimeStamp | Others |
因此,用户数据在Flash中是像下面一样子存储的:
以上图为例,如果我们读取物理地址Pa x,就能读取到Meta data x和User data x,而Meta data是有逻辑地址La x的,因此,我们就能获得映射: La xà Pa x。
映射表的恢复其实很简单,只要全盘扫描整个Flash空间,就会获得所有的映射关系,最终完成整个映射表的重构。
原理简单,但实现起来还有一些问题需要考虑。比如,同一逻辑地址,用户可能写过若干次,在Flash空间,该逻辑地址对应的数据有很多是旧数据,只有一笔是新数据,那么如何甄别哪些数据是旧的,哪个数据是最新的呢?如何让逻辑地址映射到最新数据所在的物理地址呢?
以上图为例,SSD起初把逻辑地址La 2的数据写在物理地址Pa 2上;后面,用户又改写了那笔数据,SSD把它写到了物理地址Pa 8上。我们知道,用户最后写入的数据总是最新的。在这里,时间戳(TS,Timestamp)帮上大忙了,哪个值大,就表示哪个是最后写入的。SSD就是依赖Meta data中的时间戳来区分新旧数据的。上图中,在全盘扫描时,假设扫描顺序是从物理地址Pa 1到物理地址Pa x,对逻辑地址La 2来说,开始会产生映射La 2à Pa 2, 但扫描到Pa 8时,发现时间戳比之前的更新,于是新的映射取代旧的映射,最后得到映射关系:La 2à Pa 8.
全盘扫描有一个问题,就是映射表恢复很慢,所耗的时间与SSD容量成正比。现在SSD容量都到TB级别,全盘扫描映射方式,重构映射表需要花费几分钟甚至几十分钟,这在实际使用中,用户是不能接受的。
那SSD内部怎么快速恢复映射表呢?我们先来看一段冬瓜哥的名著《大话存储》里面讲NetApp快照技术的文字:
可见,NetApp的NAS设备自带的文件系统会定期把新写的数据和元数据写到磁盘上的空闲空间,这个元数据就是数据保存位置的指针。SSD内部FTL其实就是个文件系统,映射表就是元数据,所以,SSD内部保证数据完整性的方法和NetApp的CheckPoint技术类似。目前主流的消费级SSD都采用了这种定期备份的技术来快速恢复,企业级SSD不需要快速恢复,有些只需要全盘扫描就可以了。
SSD在使用的过程中,如果能隔一段时间就把映射表写到Flash中去,比如,SSD每写千分之一容量的数据时,就把映射表写入到Flush中去,那么在上电恢复的时候就快多了。下次上电恢复的时候,把之前的映射表加载到内存,然后只需扫描那些可能在最近一次映射表备份之后被写过的物理块就可以恢复由于异常掉电丢失的映射关系。
最后总结一下:
SSD异常掉电时,如果有电容供电,那么数据一般不会丢失。为什么是一般?因为如果电容放电时间不足以维持整个RAM数据写到Flash中去,也是会导致部分数据丢失,也还是需要全局或者局部扫描方式找回部分数据。
如果没有电容,那么缓存在SSD内存中的用户数据会丢失,而写入到Flash中的数据可以通过映射表重构找回。映射表的重构有全局扫描和局部扫描两种方式,前者实现起来简单,但需花费很长时间来重构;后者实现起来较复杂,但恢复速度快。
需要说明的是,如果是正常掉电,那么SSD内存中的用户数据和映射表都会在掉电前Flush到Flash中。下次上电的时候,直接从Flash上加载映射表,不需要所谓的映射表重构。
想要每天看一条SSD文章吗?扫一扫,微信关注我们!或者微信搜索公众号ssdfans关注。