SSD
固态硬盘SSD(Solid State Drive)
闪存组织
- 闪存(Flash Memory)
- 1984:NOR flash
- 1987:NAND flash
- 1992:SSD
- NOR flash vs NAND flash
- NOR是字节寻址,NAND是页寻址
- NOR读延迟比NAND低100x
- NOR擦除时间比NAND高300x
- NOR用于取代ROM,存可执行代码
- NAND用于大量持久化存储设备
- 信息存储方式
- SLC:1 bit/cell 2个值 0/1
- MLC:2 bit/cell 4个值 00/01/10/11
- TLC:3 bit/cell 8个值
- QLC:4 bit/cell 16个值
NAND闪存组织
- Flash package
- 多个 die
- Die
- 多个 Plane/Bank
- Plane/Bank
- 很多块(擦除块)
- 一些寄存器
- 块(Block/Erase Block)
- 很多页
- 页(Page)
- 由数据区与OOB(Out of Band)区构成
- 数据区用于存储实际数据
- OOB区用于记录
- ECC
- 状态信息:Erased/Valid/Invalid
- Logic Page Number
- 页大小
- SLC通常为2KB8KB,TLC通常为4KB16KB
- 块大小
- SLC通常为128KB、256KB...
- TLC通常为2MB、4MB...
闪存的操作接口
- 读:Read a page
- 读的粒度是页
- 读很快,读延迟在几十微秒
- 读延迟与位置无关,也与上一次读的位置无关(和磁盘不同)
- 擦除:Erase a block
- 把整个块写成全1
- 擦除的粒度是块,必须整块擦除
- 很慢:擦除时间为几个毫秒
- 需软件把块内有效数据拷贝到其它地方
- 写:Program a page
- 擦除后才能写,因为写只能把1变成0
- 写的粒度是页
- 写比读慢,比擦除快,写延迟在几百微秒
页的状态
- 初始状态为Invalid
- 读时,不改变页的状态
- 擦除时,块内所有页的状态变为Erased
- 写时,只能写状态为Erased的页,写后页状态变为Valid
闪存的性能和可靠性
- 性能
- 写延迟比读高10倍以上
- 写延迟波动幅度大
- 擦除很慢:约为磁盘定位延迟
- 延迟随密度增加而增长
- 可靠性
- 磨损:擦写次数有上限,随密度增加而减少
- 干扰:读写一个页,相邻页中一些位的值发生翻转
- 闪存特性
- 读延迟很低:随机读的性能远优于磁盘
- 写慢:必须先擦除再写,约为磁盘写(ms级)
- 磨损:每个块擦写次数有上限
基于闪存的SSD
- 用很多闪存芯片来构成一个持久化存储设备SSD
- 多个闪存芯片:并行I/O,提高I/O性能
- 与主机的接口:提供标准块设备接口
- 数据缓存和缓冲:SRAM/DRAM
- 闪存控制器(硬件)和FTL(固件):控制逻辑
- 主机命令转换成闪存命令(Read/Erase/Program)
- 逻辑块地址转换成闪存的物理地址(页/块)
- 缓存替换
FTL
最简单的FTL:直接映射
- Direct Mapping
- 逻辑块的第N块直接映射到物理的第N页(假设逻辑块与物理页都为4KB)
- 读操作容易:读逻辑第k页
- 读物理第k页
- 写操作麻烦:写逻辑第k页
- 第k页所在闪存块(记为B0)
- 把B0整个块读出来
- 把B0整个块擦除
- B0中的旧页和新的第k页:以顺序方式一页一页再写入B0
- 缺陷:写性能极差
- 每写一个页,要读整个块、擦除整个块、写整个块
- 写放大
FTL改进:异地更新
- 核心思想:异地更新(out-of-place update)
- 不再执行原地更新
- 每次写页,写到一个新位置(新的物理页地址)
- 页级映射
- 页级映射表:LPN -> 物理页地址PPN
- 整个放在内存中
- 持久化:利用页的OOB区来保存映射表
- 随着写页而被写到闪存
- 掉电或重启,扫描OOB区来恢复映射表
- 优点:
- 性能好:减少写放大
- 可靠性好:映射关系被自动写入闪存
- 问题:
- 重写产生垃圾页
- 每次写到新位置,导致原先页的内容无效
- 内存开销大
- 映射表全部放内存
- 映射表的大小与SSD容量成正比
- 重写产生垃圾页
- 页级映射表:LPN -> 物理页地址PPN
- 写一个逻辑页k
- 寻找一个空闲页p(例如当前擦除块中下一个空闲页p)
- 在映射表中记录:逻辑页k -> 物理页p
- 读一个逻辑页k
- 查映射表,获得逻辑页k对应的物理页地址p
- 读物理页p
垃圾回收
- 思想
- 选择一个含垃圾页的块
- 把其中的有效页拷贝到其他块中(先读再重写)
- 回收整个块,并把它擦除
- 如何判断有效页?
- 每个物理页记录它对应的逻辑页地址(OOB区)
- 查映射表,如果映射表记录的 PPN=该页,是有效页
- 问题:开销非常大
- 有效页需要拷贝:先读再重写
- 开销与有效页所占的比例成正比
- 解决办法:超配(over-provisioning)
- 实际物理空间比用户所见空间更大:多15%~45%
- 例如,用户看到100GB的SSD,实际上内部是120GB
- GC时将数据写入 over-provisioning space,减少对性能的影响
- GC一般在SSD后台执行,尽量再设备不忙时执行,但是受限于空闲页的数量
- 空闲页不足的时候,即使设备忙也需要开始执行GC
- 实际物理空间比用户所见空间更大:多15%~45%
块级映射(Block-Level Mapping)
- 块级映射
- 逻辑地址空间划分为chunk,chunk size = 擦除块(物理块)size
- 映射表:chunk# -> 擦除块(物理块)地址 PBN
- 读一个逻辑页
- 逻辑页地址 = chunk# || 偏移
- 用chunk#查映射表,获得相应的擦除块地址PBN
- 物理页地址 = PBN || 偏移
- 问题:小规模写性能差
- 写粒度小于擦除块:拷贝有效页(读 & 写),导致写放大
- 小写很常见:擦除块通常较大(大于256KB)
混合映射(Hybrid Mapping)
- 思想
- 将擦除块(物理块)划分为两类:数据块和日志块
- 写逻辑页时都写入日志块
- 数据块采用块级映射,数据映射表
- 日志块采用页级映射,日志映射表
- 适当的时候把日志块合并为数据块
- 读一个逻辑页
- 先查日志映射表,按页级映射的方法
- 如果没找到,再查数据映射表,按块级映射的方法
合并方式
- Switch Merge
- 直接把日志块转成数据块:前提是整个日志块的页序与原数据块中的页序一致
- 把原来的数据块回收擦除
- 优点:开销低,只修改映射表信息,无数据拷贝
- Partial Merge
- 把数据块中有效页拷贝到日志块:日志块中页序与原数据块中的页序一致
- 把日志块转成数据块,把原来的数据块回收擦除
- 有数据拷贝开销
- Full Merge
- 分配一个新的日志块,从数据块和日志块分别拷贝有效页到新日志块
- 把新日志块转成数据块
- 把原来的数据块和日志块都回收擦除
- 开销很大:需要拷贝整个物理块的数据(读 & 写)
磨损均衡
- 目标
- 让所有块被擦除的次数近似
- 动态磨损均衡
- 每次写时,选择擦除次数较少或最少的空闲块
- 局限性:不同数据的修改频率不同
- 例子:只写一次的数据(static data),很少写的数据(cold data)
- 静态磨损均衡
- 动态磨损均衡不考虑不会被回收的物理块,例如长时间不被修改的物理块(写冷块)
- 不再被写,不再有磨损
- 解决办法:FTL定期重写冷块,将其写入磨损较多的块
总结
- SSD FTL的主要功能
- 地址映射
- 垃圾回收
- 磨损均衡
- 请求调度
- 缓存管理
- 坏块管理