【存储技术基础】固态硬盘
主要由Flash Memory 和FTL组成
Non-Volatile Memory 提供低延迟持久性的内存/存储,也可以用来做内存
根据延迟数量级,一般用PCM做内存,Flash Memory做外存
0x00 Flash Memory
闪存原理
类型
NOR闪存
- 存储密度低
- 可字节改写
NAND闪存(主流)
- 存储密度高
- 不可覆盖写
用于外存需要较高的存储量级,一般用NAND
闪存单元
读:电压代表不同数值
写:电子注入
相比晶体管添加了浮栅门,保存电子
原理其实比较简单,非电子系就不做太详细的研究了
闪存页(4KB,8KB,16KB,读写单元),阵列中的每一行
闪存块(擦除单元),由多个页组成的单元

选中行和列,然后将数据加载到Sense Amplifiers
存储单元有两个阈值的电压,可以根据两个电压的中点作为读电压,2.5V读电压时左边通电,数据为1,右边则不通电,数据为0

Pass Through
选取一个较大的电压,使得所有的单元都接通,数据为1,不影响其他行的状态

如图所示的存储结构,在第二行施加2.5V电压,其他行施加5V,最终读取数据为0011

上述为SLC,Single Level Cell,单存储单元
多比特闪存
多比特闪存单元MLC,包含2Bits 4个Level的数据
TLC 3 Bits 8个Level
QLC 4 Bits 16个Level
多比特使用格雷码来编码
使用格雷码使得相邻单元只有一位差异,方便纠错
多比特提高了存储密度,但是提高了错误率,因为施加的电压差距很小。可靠性会降低。

对于多比特的写,MLC分为高比特和低比特,对于低比特的状态加偏移电压确定高比特,在低比特时需要加的电压较大,操作难度低,运行速度快,在高比特时需要加的电压小,波形的间距小,操作难度高,运行的速度较慢。

对于多比特的读,先看lower bit,加一次电压,即可筛选出低位的0,1,再加两次电压确定upper bit。因为upper bit为0的在中间部分,为1的在两侧,因此需要在两个分界线分别加一次电压来确定upper bit为多少。

闪存
Block的大小的一种配置:
一行有两个Page,Upper Page和Lower Page,每个单元中,低位构成Lower Page,高位构成Upper Page,有128个单元,128K/8=16KB
有64列bitlines,一个block的大小即为16KB*64*2=2MB
,一般按照此比例配置Block
写入时按照固定顺序,写入高低页面相互独立,不能同时写,在写入加压时容易使相邻单元发生数据偏移,要降低错误率
写入是需要先擦除再写入,擦除整个块

特性
读写粒度
闪存页读写粒度:
- 4KB,8KB,16KB必须全部读取或者写入
- us延迟
闪存块擦除力度
- 2MB擦除
- ms延迟,可以通过FTL来优化
不可覆盖写
写前需要擦除,读写粒度与擦除粒度不同
存在64bytes的OOB(out of bound area),保存ECC,用于纠错,容忍写入时部分比特出错

有限次擦除
随着擦除次数的增加,存储单元不能可靠的保持状态(存储数据)。
氧化层老化变薄,束缚电子能力变弱
- 耐久性 变薄地次数
- 保持力 不通电可以放置的时间
SLC:10w次
MLC:1w次
TLC:1k次
根据特性设计FTL固件来

0x01 FTL
固态硬盘整体构成

SSD中的通道可以并行,通道中也可以并行读取,每个Plane中有寄存器,暂时存储准备好的数据。不同单元并行,因此内部带宽大

垃圾回收
page对于OS而言,是写入时的block
Page三种状态
- 空闲 free page
- 有效页 live/valid page
- 无效页 dead/invalid page

需要擦除无效页,先移走有效页,然后再对一整行进行擦除,转为空闲

时间开销:
- 复制有效数据到$(R_{Latency}+W_{Latency})*N$,N是移动page的数量
- 擦除产生的开销 ms级延迟
GC策略
要解决的问题:
- 何时启动GC
- 选中那些/多少Block进行GC
- 有效的页如何被转写
- 新数据写到哪里
GC的时间开销:
- 块擦除的时间 ms
- 有效页的复制时间
贪心策略:
- 找到脏页最多的block来进行擦除
优化:
- Age
- Hot/Cold 数据隔离,分组问题
磨损均衡
优化寿命,有静态和动态策略
静态:周期性的调整冷热数据存储的位置
冷热数据的分区:将冷数据放在一起,热数据放在一起
FTL简介
-
维护映射,虚拟地址到物理地址
-
使用SRAM存储映射
-
向上层隐藏擦除操作:
-
避免原地更新->异地更新
-
更新一个新页面
-
高性能的垃圾回收和擦除
-
OOB有物理地址到虚拟地址的映射,用于掉电恢复,这里引用一段wisc的OSTEP中的一段解释(44 Flash- based SSD)。
OOB保存的在每个页中映射信息,当掉电或者重启时用它在内存中重建映射
为了防止在重建时扫码整个SSD,可以使用日志或者检查点的方式来加速这个过程
大致看了一下OSTEP,记得是jyy老师推荐的教材,希望以后有时间读一下

Page-Level FTL
原理类似OS中的页表,由Logical Page Number查询页表得到Physical Page Number
缺点是页表占用很大的空间

Block-Level FTL
保持Block 到Block的映射
先查找到对应的Block,在根据offset得到page,块内的页码偏移offset是固定的

优点是占用空间很小,缺点是GC负载增加
原因:offset在不同Block中保持不变,在异地更新时,要选择其他block中相同的offset进行写入,如果选中的block已经存在数据,需要把数据迁移。【TODO 这里讲得不是非常的清楚】
Hybrid FTL
对写入分为新/旧数据,新写入的数据用Page-Level Mapping效率高,写入Log Blocks作为缓冲,之后再更新到Data Blocks
旧数据因为写入后更新相对不频繁,使用Block-Level Mapping,写入Data Blocks