深入理解闪存磨损均衡算法
核心问题:为什么需要磨损均衡?
要理解磨损均衡,首先要认清 Flash 存储器(包括 NAND Flash 和 NOR Flash)的物理限制。
- 有限的擦写次数:Flash 存储单元在经历一定次数的擦除操作后,会因物理损耗而失效。这个次数被称为耐久度。
- SLC NAND:约 10 万次
- MLC NAND:约 3 千至 1 万次
- TLC NAND:约 500 至 1.5 千次
- QLC NAND:约 100 至 500 次
- 擦除操作的特殊性:Flash 不能像 RAM 一样直接覆盖写入。它必须先进行擦除(通常按'块'进行,如 128KB/256KB),将整个块变为全 1,然后才能进行编程(将需要的比特从 1 变为 0)。
典型场景:假设文件系统的元数据(如 FAT 表)固定存储在同一个 Flash 物理块上。每次文件更新,这个块都需要被擦写一次。即使该块理论寿命为 1 万次,在频繁写入的系统里,可能几周甚至几天就会用尽寿命,导致整个存储设备提前报废,而其他大部分块可能还'全新未使用'。
磨损均衡的目标很明确:通过算法,让所有 Flash 物理块的擦写次数均匀分布,避免某些'热点'区块被过早写坏,从而将整个存储设备的总寿命延长至接近其理论最大值。
实现层次与核心思想
磨损均衡算法主要在闪存转换层(FTL)中实现。FTL 是介于文件系统(如 FAT32, ext4)和物理 Flash 芯片之间的固件层,负责地址转换、坏块管理、垃圾回收和磨损均衡。
其核心思想是将文件系统看到的'逻辑地址'与 Flash 存储器的'物理地址'分离开来,并动态地改变它们之间的映射关系。这意味着数据写入哪里,不再由文件系统决定,而是由 FTL 根据当前各块的磨损情况智能调度。
主要磨损均衡算法分类
磨损均衡算法主要分为两大类:动态磨损均衡和静态磨损均衡。
1. 动态磨损均衡
这是最基本的形式。
- 原理:当需要写入新数据时,FTL 总是从空闲块池中选择一个擦除计数最小(即最年轻)的块来使用。
- 运行机制:
- FTL 维护一个所有空闲块的列表,并记录每个块的擦除次数。
- 当有写入请求时,算法从这个列表中找出擦除次数最少的块。
- 将数据写入该块,并更新逻辑到物理的地址映射表。
- 该块被移出空闲列表,其擦除计数增加。
- 优缺点:实现相对简单,能有效防止新写入的数据集中消耗少数几个块。但无法解决'冷数据'问题——如果一个数据写入后就不再修改,它所占用的物理块就不会再被擦写,导致块之间的磨损差异逐渐拉大。
2. 静态磨损均衡
这是更高级、更有效的方法,也是现代 SSD 和 eMMC/UFS 中的标准做法。
- 原理:不仅在选择空闲块时考虑磨损,还会主动地将'冷数据'从低磨损的块中搬移到高磨损的块中,从而让那些闲置的、低磨损的块也参与到磨损循环中来。
- 运行机制:
- 同样采用动态磨损均衡的策略来选择空闲块。
- 系统会周期性地或在特定条件下(如磨损差异超过某个阈值)启动数据迁移。
- FTL 会寻找一个存放着冷数据的、磨损计数很低的物理块(Block A),以及一个磨损计数很高的空闲块(Block B)。
- 将 Block A 中的有效数据复制到 Block B 中。
- 更新地址映射表,指向新的 Block B。
- 最后,将原来的 Block A 擦除,并放入空闲块池。这样,这个原本闲置的低磨损块就变成了可用块,准备接受新数据的写入。
- 优缺点:极大地改善了磨损的均匀性,使所有块的寿命得到最大程度的利用。缺点是增加了写放大,因为复制冷数据本身会产生额外的写入操作,这些操作对用户来说是多余的,但为了均衡寿命又是必要的。


