
FTL 与垃圾回收:SSD 是如何处理“碎块”的逻辑迷宫?

如果说 NAND Flash 是 SSD 的肌肉,那么 FTL(闪存转换层,Flash Translation Layer) 就是它的大脑。为了掩盖“不能低成本原地覆写”这一物理事实,FTL 必须在后台疯狂地玩一场“逻辑地址与物理地址的拼图游戏”。
1. FTL 的核心职责:逻辑到物理的映射
当操作系统执行 write(LBA=100, data=X) 时,它写的是一个逻辑块地址(Logical Block Address)。但在实际闪存中,LBA 100 对应的物理位置可能随时变化。地址映射表:
- FTL 内部维护着一张巨大的表,用来记录 LBA -> PBA(物理地址) 的映射关系。这张表通常会借助控制器上的 DRAM 或 SRAM 进行缓存和加速,而不一定完全常驻在独立 DRAM 中。
- 重定向写入:当第二次写入 LBA 100 时,FTL 不会去覆盖原来的物理页,而是找一个新的空闲页写入数据,并迅速更新映射表,让 LBA 100 指向新的物理页。原来的物理页则变成“失效页(Stale / Invalid Page)”,等待后续回收。
这就是 SSD 最核心的伪装术:主机看到的是“覆盖写”,闪存内部实际发生的是“异地写入 + 映射更新”。
2. 垃圾回收(GC):SSD 的“碎片清理”动作
随着不断写入,闪存中会散布越来越多不再使用的“垃圾页”。FTL 必须通过 GC(Garbage Collection) 在后台把这些空间重新整理出来:
- 挑选 Block:FTL 寻找那些包含较多无效页的 Block
- 存活页搬迁:将该 Block 中剩余的有效数据读出,再写入其他空闲
- Block擦除(Erase):确认有效数据都搬走后,对整个 Block 执行擦除,使其重新变成可用空闲块
这就是 GC 的代价:它不仅消耗闪存的擦写寿命,还会占用宝贵的内部带宽。如果磁盘接近写满,GC 往往就不能再“从容地”在后台运行,而必须更频繁地与前台写入竞争资源。此时你感受到的,就是 IO 性能抖动,甚至是明显的“卡顿”。
3. 为什么 TRIM 指令是救命稻草?
如果操作系统不告诉 SSD 哪些逻辑块已经失效,SSD 就无法准确知道哪些物理页可以尽早回收。TRIM 可以理解为操作系统向 SSD 发出的“失效通知”。
- 当你在操作系统里删除一个文件时,OS 通常并不会立即清空对应的数据内容,而只是更新文件系统元数据
- TRIM 命令会进一步告诉 SSD 控制器:“这段 LBA 范围已经不再需要了”
- FTL 收到后,会将对应的物理页直接标记为“无效”,跳过昂贵的搬迁步骤,从而直接擦除所在的 Block。这极大地降低了 GC 的压力。
4. 磨损均衡:让闪存“寿命均摊”
如果某个热点数据(比如日志文件)持续写入同一组逻辑地址,而底层物理块又总是集中落在少数区域,那么这些物理块就会被更频繁地擦除,导致局部“早夭”。因此需要均衡算法让整块 SSD 的磨损尽量均匀,避免某些块提前报废。
- 动态磨损均衡:FTL 在分配新写入位置时,会尽量选择擦除次数较少、寿命更健康的物理块
- 静态磨损均衡:FTL 还会在必要时,把那些长期不变的“冷数据”从磨损较轻的块搬走,腾出这些健康块给高频写入数据使用,同时把冷数据迁移到磨损更高但仍可用的块上
5. 关键权衡:空间的“过度预留”(Over-Provisioning)
为了避免 GC 成为性能瓶颈,高质量 SSD 通常会预留出一部分主机不可见的物理容量(7%~12%),称为 Over-Provisioning(过度预留)。
- 空间换性能:预留空间越大,FTL 就越有余地安置搬迁中的数据
- 空间换寿命:空闲块越充足,GC 压力越小,写放大(WAF)通常就越低,闪存寿命和稳态性能也越容易维持
FTL 的本质,是通过牺牲一部分内存资源(用于维护映射和元数据)、一部分物理容量(用于过度预留),来换取随机写入能力、性能稳定性和闪存寿命。
SSD 性能的真正差异,往往不只在于闪存芯片本身,更在于 FTL 算法的成熟度——它如何在“清理垃圾”、“响应读写”、“控制写放大”和“延长寿命”之间,找到那个微妙的平衡点。