只读分享解决方案文档原理方案设计📅 2026-10-14🔖 Rev 1.0⏳ 还有3日到期
🔧解决方案&应用市场分析 -> 原理方案设计 -> 电子设计&技术探讨 -> 磨损均衡算法对比_技术探讨

磨损均衡算法对比_技术探讨

同系列 · 原理方案设计
扫码打开本页
微信扫码

磨损均衡算法对比

动态均衡 / 静态均衡 / 全局与混合均衡 —— 把擦除次数均匀摊到所有块上的三层算法、三项代价与选型边界 | 编制日期 2026-10-14 | 版本号 Rev 1.0

3 层算法
动态 / 静态 / 全局与混合
分工不同,不是三代替代关系
3 项代价
迁移写入、表空间、擦除成本
核心权衡,三者不可兼得
1 个失效场景
动态均衡最大的软肋
冷数据块永远不被迁移
4 级粒度
页 / 块 / 段 / 区域
粒度越粗,表越小、均衡度越低
报告总结

几乎每一份存储器件的技术简介都会写一句「内置磨损均衡」,但它从来没说清楚:均衡到底均衡了什么、均衡到什么程度、为此付出了多少额外写入。于是现场就出现两类典型困惑——一类是器件标称寿命远没到,实际却提前出现坏块与写入失败;另一类是开了均衡之后写放大明显变差,性能与寿命反而一起下滑。

这两类困惑的根子是同一个:擦除次数天然不会自己均匀分布。热数据反复改写少数块,冷数据长期压着一批几乎不参与磨损的块,差距会随时间单调拉大。磨损均衡不是「让器件更耐用」,而是把有限的总擦除预算从用不完的地方搬到不够用的地方。

这份文档把这件事拆成三层算法来讲:动态均衡只管挑空闲块,静态均衡主动搬迁低磨损块上的冷数据,全局与混合均衡把两者融合并放大到段与区域粒度。三条主线之外,给出统一的代价框架、参数起点、可观测性指标与失效排查路径。所有数值均为行业经验区间,以正式 datasheet 与实测为准。

结论: 磨损均衡的本质只有一句——把擦除次数均匀摊到所有块上,让整盘寿命由「所有块的平均磨损」决定,而不是由「磨损最重的那一个块」决定。 三层算法的分工因此非常清楚:动态均衡只在空闲块里挑擦除计数最低的那个来承接新写入,冷数据块永远不会被它迁移,这是它最大的失效场景;静态均衡主动把低磨损块上的冷数据搬到高磨损块上,用额外迁移量换均衡度;全局与混合均衡把两者融合,并把管理粒度放大到段与区域,用更粗的粒度换更小的表。 三者共同的核心权衡是「均衡效果 vs 迁移开销 vs 表规模」,这三项不可兼得——要更高的均衡度就得付出更多迁移写入,要把表做小就得接受更粗的粒度与更低的均衡度。选型不是挑「最好的算法」,而是挑在你的负载形态下代价最合适的那一个。

读者路径

  • 只想搞懂为什么磨损会不均:第 1 章,重点看 1.2 热冷数据与 1.3 磨损度量。
  • 要理解三层算法的差别:第 3 章(动态)、第 4 章(静态)、第 5 章(全局与混合),这是本文主干。
  • 要做选型:第 6 章(横向对比与选型矩阵)+ 第 11.1 节(决策树)。
  • 要调参数:第 8 章(阈值、批量、周期、冷热窗口)与第 9 章(度量)。
  • 现场出问题了:第 10 章(误区与失效模式)+ 附录 C(排查手册)。
  • 只想要速查表:第 12 章与附录 B 就够了。

1. 磨损为什么天然不均匀

磨损均衡之所以存在,前提只有一个:如果不加干预,擦除次数在各块之间一定是不均匀的,而且差距会随时间单调拉大。这一章先把「为什么会不均」讲透,再定义「用什么量来描述不均」,最后给出磨损均衡能做到与做不到的边界。后面所有算法的比较,都建立在这一章的三个事实之上。

1.1 写入分布不均匀的根源

一个很自然的想象是:主机写了多少数据,NAND 上就均匀摊掉多少磨损。这个想象在两处同时出错。

  • 第一处:写入量按地址加权,不是按容量均摊。擦除次数是「有多少次写入落到了这块上」的累积结果。写入落在哪块由逻辑地址决定,而逻辑地址的访问频率在不同区间之间可以相差几个数量级。容量占一半的区间,完全可能只吃掉个位百分点的写入。
  • 第二处:擦除的单位是块,写入的单位是页。一次擦除覆盖整个块,但触发这次擦除的可能只是块里某几页的改写。于是「少量热点页」就能拖着「整块」反复擦写。

把这两处合起来,写入分布不均的根源可以归成四类,它们几乎总是同时出现:

根源典型形态空间分布特征时间分布特征对擦除次数的直接影响
元数据反复改写文件系统元数据、目录项、超级块、分配位图集中在极少数固定逻辑区高频、持续、贯穿全生命周期把少数块推到远高于均值的计数
日志与记账循环写日志、计数器、掉电记账区、磨损计数本身集中在环形或固定区域周期性、可预测形成稳定且长期存在的热点
固件与只读资源固件镜像、字库、配置、只读资源包占容量大头写一次后长期不再改写对应块长期停在低计数,几乎不参与磨损
随机小写命中窄区间小粒度随机写、数据库页更新、参数区命中少数区间突发、抖动大在窄区间内制造局部高计数块

这四类里,前两类制造「热端」,第三类制造「冷端」,第四类介于两者之间并放大抖动。热端与冷端同时存在,才是磨损不均的完整形态——只看到热端会误以为「把热数据摊开就行」,而真正让均衡失效的往往是冷端那批一动不动的块。

最常见的理解偏差

把磨损不均归因为「器件质量问题」或者「颗粒一致性差」是最常见的误判。颗粒之间确实存在耐久差异,但在正常工作负载下,负载分布带来的计数差距通常远大于颗粒本身的耐久离散。也就是说:同一批器件在不同的写入模型下,寿命可以差出很多倍,而这个差别主要来自负载,不是来自器件。

1.2 热数据与冷数据

描述写入分布最常用的切分是热数据与冷数据。这条切分不是按数据类型分的,而是按「改写频率」分的:

  • 热数据:改写频率高,逻辑地址被反复命中。它可能只占容量的很小一部分,却吃掉大部分擦除次数。
  • 冷数据:写入之后长期不再改动。它通常占容量的大头,但擦除计数长期停在写入时的水平。
  • 温数据:介于两者之间,改写频率随业务阶段变化。实际系统里真正的中间态往往比两端更难处理,因为它会「变热」也会「变冷」。

从工程经验看,冷数据在容量占比上经常是大头量级(常见说法是占到容量的五到七成,具体取决于设备类型与使用阶段),而它吃掉的擦除次数往往只是一小部分;热数据则相反。这个「容量占比与磨损占比倒挂」的现象,是后面所有均衡算法存在的前提:如果两者不倒挂,均匀摊开就没有意义。

维度热数据温数据冷数据
改写频率高,可能每秒到每分钟量级中等,随业务阶段波动极低,写入后长期不变
容量占比常为小头中等常为大头
磨损占比常为大头中等常为小头
擦除计数走势持续领先并拉大差距跟随均值上下移动长期停在低位
对均衡的意义是迁移的主要目标源判定最难,容易误判是静态均衡要腾挪的对象
典型例子元数据、日志、计数器用户增量数据固件、只读资源、归档

这里有一个必须提前说清的点:冷热是动态的。今天的冷数据可能因为一次固件升级变成温数据,明天的热数据也可能因为业务切换彻底冷下来。因此冷热判定不能只看「最后一次写入时间」,而要看一段时间窗口内的改写次数——窗口多长,就是第 8.4 节要讨论的参数。

1.3 磨损度量的定义

在谈「均不均」之前,必须先有可计算的量。工程上最少需要下面几个量,它们的定义要严格区分:

量含义怎么算用途注意点
擦除计数单个块累计被擦除的次数每次成功擦除后加一均衡的直接输入必须持久化,掉电不能丢
耐久上限块在规格上可承受的擦除循环数来自器件规格书归一化分母随颗粒类型与代际差异很大
磨损度已消耗寿命的比例擦除计数 / 耐久上限横向比较不同块分子分母必须同源
剩余寿命还能承受的擦除次数耐久上限 - 擦除计数坏块与替换决策不是时间的直接换算
均值全部块擦除计数的算术平均求和 / 块数整盘磨损水平被极值拉偏时需配合中位数看
极差最高计数与最低计数之差最大值 - 最小值最直观的均衡指标只看两个块,易受异常值误导
标准差计数分布的离散程度对偏差平方求平均再开方分布的稳定性对少量离群块不敏感
分位数把分布切成若干段的边界值排序后按位置取值看长尾与冷端比极差更能反映整体形态
度量的三条口径纪律

第一,分子分母必须同源:算磨损度时,擦除计数与耐久上限要来自同一颗粒类型与同一口径,不能拿一类颗粒的计数除以另一类的上限。

第二,均值的口径要写清楚:是「所有块的算术平均」,还是「只统计在用块」,还是「按容量加权」。三种口径在冷端占比高时差别很大,混用会得出自相矛盾的结论。

第三,分布类指标必须说明统计范围:是否包含坏块、是否包含替换块、是否包含保留区。这些块数量虽少,却往往是极值所在,包含与否会显著改变极差。

这几个量里,极差与标准差是描述「均不均」的主力,均值描述「磨到什么程度」,磨损度描述「还剩多少」。它们回答的是三个不同问题,混用会直接导致误判:均值很低不代表均匀(可能是一半块为零、一半块已接近上限),极差很大也不代表马上要坏(可能最高值离上限还很远)。

还需要区分两个容易混淆的口径:主机侧写入量与 NAND 侧写入量。磨损由后者决定,而用户体验由前者决定,两者之间的比值就是写放大系数。任何「按写入量估算寿命」的算法,都必须先把主机侧换算成 NAND 侧,否则会系统性低估磨损。

1.4 磨损不均的后果

磨损不均本身不是故障,它是一种把寿命提前消耗掉的效率损失。后果按严重程度递进:

  1. 整盘寿命由最重的块决定。只要有一个块先触顶失效,可用容量就开始掉,哪怕其余块的剩余寿命还很充裕。这部分「用不完的寿命」是纯损失。
  2. 可用容量随时间衰减。随着坏块与替换块增加,可提供给主机的容量逐步下降,而且下降往往不是线性的。
  3. 写放大随之抬高。可用空间变紧会迫使垃圾回收更频繁、更激进,进一步增加 NAND 侧写入,形成正反馈。
  4. 数据保持裕量被吃掉。擦除次数高的块,电荷保持能力通常更差;同一批数据落在高计数块上, retention 风险更大。
  5. 性能抖动变大。回收压力上升会带来更长的写停顿,表现为偶发的长尾延迟而不是平均性能下降。
  6. 一致性风险。如果计数表与实际物理状态不一致,可能把数据搬到已经接近寿命末期的块上,把本来可控的问题变成不可控。
  7. 评估失真。如果只用整盘均值或总写入量来估算剩余寿命,会系统性高估——因为真正先失效的是分布右端那一小撮块,而不是均值所代表的「典型块」。

最后一条值得单独强调:寿命评估必须用分布,不能用均值。用均值估算出来的寿命,是「把所有块的寿命借给彼此之后」的理想值,而磨损不均恰恰意味着这种借贷做不到。两者之间的差额,就是磨损均衡要挽回的目标,也是不做均衡时白白损失掉的那部分。

后果直接表现为什么会这样能否靠均衡挽回
寿命提前触顶少数块先失效,整盘剩余寿命充裕寿命由最高计数块决定能,这是均衡的主战场
可用容量衰减可用容量随使用时间下降坏块与替换消耗物理容量部分能,取决于坏块原因
写放大抬高主机写不变,NAND 写上升回收变频繁、搬迁叠加不能,均衡本身还会抬高
保持能力变差高计数块上数据出错率上升耐久与保持特性相关间接能,通过摊平计数
长尾延迟变差偶发长时间写停顿擦除与搬迁占用带宽不能,属于均衡的代价侧
计数与物理不一致计数表失真导致误判掉电、记账遗漏、更新不同步不能,属于实现正确性问题

1.5 磨损均衡能做什么、不能做什么

把边界划清楚,比记住算法细节更重要。磨损均衡是一个分配优化,不是一个寿命创造机制。

能做做到什么程度不能做为什么不能
把擦除次数摊得更均匀把极差与标准差压下去凭空增加总擦除预算总预算由颗粒与容量决定
让冷端块参与磨损通过主动搬迁实现在不搬迁的前提下搬冷数据冷数据不动,计数就不会涨
降低由磨损不均导致的寿命损失显著,是主要收益降低由写入量本身决定的磨损写入量是需求侧决定的
改善高计数块的保持风险通过摊平计数间接改善修复已经物理损坏的块物理损坏不可逆
配合回收减少无效擦除有协同空间替代垃圾回收两者解决不同问题
让整盘寿命接近平均水平这是均衡的目标上限让整盘寿命超过平均水平平均就是上限
一句话边界

磨损均衡只能把已有的擦除预算重新分配,不能增加预算总量。它的收益上限是「让整盘寿命等于所有块的平均寿命」,而代价是为此付出的额外迁移写入与表空间。因此均衡做得越激进,收益增长越慢、代价增长越快——这个非线性关系是所有参数选择的底层约束。

1.6 本文主线

全文围绕一条主线展开,后面所有章节都是它的展开:

主线

磨损均衡的本质是把擦除次数均匀摊到所有块上。

三层算法的分工:动态均衡只管「挑空闲块」,冷数据块永远不被迁移,这是它最大的失效场景;静态均衡主动搬迁低磨损块上的冷数据,用额外迁移量换均衡度;全局与混合均衡把两者融合并放大到段与区域粒度。

核心权衡是「均衡效果 vs 迁移开销 vs 表规模」,三者不可兼得。

沿着这条主线,本文的推进顺序是:第 2 章先把问题形式化(合格判据、三项代价、信息范围、分工、粒度),第 3~5 章分别讲三层算法,第 6 章横向对比,第 7 章讲与其他机制的耦合,第 8 章讲参数,第 9 章讲度量,第 10 章讲误区与失效,第 11 章给工程清单,第 12 章收口。

写入分布不均的四条来源,以及它们落到擦除次数上的后果来源:主机侧写入的四种形态元数据反复改写文件系统元数据总落在固定逻辑区日志与记账循环写日志、计数器、记账区形成稳定热点固件与只读资源写一次之后长期不再改动随机小写命中窄区间小粒度随机写集中在少数区间后果:擦除次数被拉开少数块擦除次数远高于均值冷数据块长期停在低擦除次数极差随时间单调拉大整盘寿命由最高计数的块决定热点吃掉多数擦除写入量按地址加权不是按容量均摊冷区长期锁死占容量大头却几乎不参与磨损差距单向累积只会拉大不会自动收敛示意图:四条来源为定性归纳,具体分布形态随文件系统、业务模型与使用阶段而变,需以实测统计为准。
图 1 · 写入分布不均从哪里来:四条来源与它们对擦除次数的影响

把图 1 的四条来源和图 2 的分布形态放在一起看,会得到两个可直接用于设计的判断:

  • 判断一:只看均值一定会误判。均值描述的是「总共磨了多少」,但决定寿命的是分布的长尾。两个均值相同的器件,一个分布紧凑、一个长尾很长,寿命可以完全不同。
  • 判断二:冷端才是动态均衡的盲区。图 2 里冷端那批块计数长期不动,任何「只在空闲块里挑」的策略都无法让它们参与磨损。要让它们参与,只有一条路——把上面的数据搬走,把热数据换进来。
把所有块按擦除次数从低到高排开:冷端几乎不动,热端一路冲高块集合上的擦除次数分布(示意,横轴为按计数排序后的块序号)冷端:计数远低于均值过渡区:跟随均值上升热端:计数远高于均值均值线高中低均值冷数据区过渡区热数据区冷端块数常占容量大头却只吃掉少量擦除,热端块数少却吃掉多数擦除 —— 这是磨损不均的定量形态。示意图:高度为定性示意,不代表任何具体器件或负载的实测值;分区边界随冷热判定窗口而变。
图 2 · 热数据与冷数据在擦除次数分布上的位置:冷端不动、热端冲高

2. 磨损均衡的基本问题与约束

在比较具体算法之前,需要先把问题形式化:「均衡」到底要均到什么程度才算合格?为此要付出什么?手上有多少信息可用?谁来做?在多粗的粒度上做?这五个问题不回答清楚,任何算法比较都会退化成口号之争。

2.1 均衡到什么程度算合格

「均匀」是一个理想极限:所有块擦除次数完全相等。工程上既达不到,也没必要达到。真正要回答的是允许多大的离散度。

可用三类判据来描述,它们适合不同的场合:

  • 极差判据:最高计数与最低计数之差,控制在均值的某个比例内。最直观,但只看两个极端点。
  • 标准差判据:计数的标准差与均值的比值(离散系数)落在某个区间内。反映整体分布,对少数离群块不敏感。
  • 分位数判据:例如把最高分位与最低分位的差值、或者中位数与最高分位的比值作为门槛。兼顾整体与长尾,是实际系统里最实用的一种。

从经验上看,一个运行良好的块级均衡,通常能把离散度压到「远小于 1」的量级(即标准差明显小于均值),并把极差控制在均值的一倍以内;而完全不做静态均衡的系统,极差常常能拉到均值的数倍。这些都是量级性参考,具体门槛必须结合器件的耐久上限与目标寿命反推,以正式 datasheet 与实测为准。

判据计算方式优点缺点适合谁
极差最大值 - 最小值一眼看懂,便于现场判断只看两点,易被异常值误导现场快速体检
离散系数标准差 / 均值反映整体,无量纲可比对少量离群块不敏感算法效果评估
分位数差高分位 - 低分位兼顾整体与长尾需要先排序,计算量略大控制器内部触发判据
触顶预警最高计数 / 耐久上限直接对应寿命风险不反映分布形态坏块与替换决策
冷端占比低计数块数 / 总块数直接暴露动态均衡盲区阈值依赖冷热定义判断是否需要静态均衡

还需要明确一个容易混淆的点:合格不等于最优。把离散度从 0.5 压到 0.3 可能需要翻倍的迁移量,而寿命收益可能只有几个百分点。因此工程上更常用的做法是设定一个目标区间,达到即止,而不是一味追求最小离散度。这个「达到即止」的门槛就是第 8.1 节的触发阈值。

还有一点:合格判据要随磨损阶段变化,不能从头到尾用同一个数字。在寿命早期,各块计数都很低,此时极差的绝对值小是自然的,判断意义不大,应该看相对离散度;到寿命后期,各块计数都接近上限,此时即使相对离散度不大,绝对极差也可能已经足以让一部分块先触顶,应该同时看绝对极差与触顶接近度。同一个判据贯穿全寿命期,是很多「到后期突然失效」的根因。

2.2 三项代价:迁移写入、表空间、擦除成本

磨损均衡不是免费的。它同时付三项代价,而且这三项彼此牵制。

代价是什么为什么会付主要受什么影响典型表现
迁移写入把数据从源块读出再写入目标块均衡必须移动数据才能改变归属迁移批量、触发频率、冷热判定准确度写放大系数上升
表空间擦除计数表、冷热标记、位图等元数据记账粒度越细,条目越多记账粒度、块数、是否需要历史窗口SRAM 占用与掉电保存开销
擦除成本腾空旧块所需的擦除动作搬迁后旧块必须回收才能复用搬迁批量、是否合并到垃圾回收带宽占用与写停顿变长

三项代价之间的关系可以概括成三条:

  • 均衡度与迁移写入正相关。要更高的均衡度,就要搬得更频繁、搬得更多。边际收益递减,边际代价递增。
  • 表规模与均衡度正相关。记到块级才能识别块间差异;记到段级,段内差异就被平均掉了,看不见也就均衡不了。
  • 擦除成本与迁移写入正相关,但可以被摊销。把均衡搬迁与垃圾回收合并执行,一次擦除服务两个目的,是降低这项代价的主要手段(见第 5.3 与第 7.1 节)。
任何一层磨损均衡,都要同时付这三项代价代价一 · 迁移写入把数据从一块搬到另一块,读出来再写进去,主机没写,NAND 写了。直接抬大写放大系数。省不掉只能权衡代价二 · 表空间要记账就得有表:擦除计数表、冷热标记、有效页位图、地址映射。粒度越细,表越大。省不掉只能权衡代价三 · 擦除成本搬迁会腾出旧块,旧块要回收就得擦除,擦除本身消耗寿命,还占用带宽与停顿窗口。省不掉只能权衡要均衡度就得接受更多迁移写入要小表就得接受更粗的粒度要低写放大就得接受更低的均衡度三项代价彼此牵制:压下一项通常会抬起另一项,选型就是在这三者之间找落点。
图 3 · 磨损均衡的三项代价:迁移写入、表空间、擦除成本

2.3 信息的可获得范围

算法能做什么,首先取决于它能看到什么。信息范围决定了均衡能力的上限,这一点经常被忽略:很多「算法效果不好」的问题,实质上是「算法看不到足够的信息」。

信息项控制器侧能否拿到主机侧能否拿到拿不到时的后果
每块擦除计数能,且是它自己维护的通常不能直接拿到无法自建均衡
坏块与替换状态能通常不暴露可能把数据搬到风险块
逻辑地址到物理块的映射能看不到,映射在器件内部无法判断数据落在哪
冷热属性(改写频率)能,靠访问统计能,且更懂业务语义控制器侧要靠窗口猜
主机逻辑上的数据重要性不能能无法做语义级冷热分层
未来写入意图不能部分能(业务可预测)只能被动响应,无法提前布局
空闲块池状态能看不到无法自己挑块

这张表直接解释了为什么磨损均衡几乎总是放在控制器侧:擦除计数、映射关系、空闲块池这三项核心信息只有控制器有。主机侧能做的主要是减少无效写入、做冷热分层、避免放大,这属于「少制造问题」,而不是「解决问题」。

2.4 主机侧与控制器侧的分工

两侧各有能做与不能做的事,把分工讲清楚可以避免大量无效的尝试。

职责主机侧控制器侧说明
维护擦除计数不做必做控制器专有信息
挑空闲块承接写入不做必做动态均衡的核心动作
搬迁冷数据不直接做必做静态均衡的核心动作
冷热识别可做语义级做统计级两侧互补,主机更准
减少元数据放大可做部分可做主机侧的收益通常更大
合并小写、对齐写入可做可做降低写放大,间接利于寿命
预留空间与容量规划可做部分可做决定回收压力
保证掉电一致性配合必做计数表必须可靠持久化
一个实用的分工原则

主机侧负责「少写、写对」,控制器侧负责「摊平」。主机侧最有价值的两件事是:减少元数据类的高频小改写,以及把真正冷的大块数据(固件、资源包)尽量一次性写入、之后不再触碰。这两件事的收益往往比纠结用哪种均衡算法更大,而且不需要任何器件内部信息。

2.5 均衡粒度:页、块、段、区域

粒度是磨损均衡最容易被忽视、但影响最大的一个设计变量。它同时决定表规模、可达均衡度、迁移代价三件事。

  • 页级:以页为记账与轮转单位。粒度最细,但擦除的单位是块而不是页,页级记账无法解决块间差异,主要用于块内页间的写指针轮转。
  • 块级:以块为记账单位。这是主流粒度,表规模与块数成正比,能直接识别块间差异,绝大多数均衡算法在这一层工作。
  • 段级:以若干块组成的段为记账单位。表规模缩小一个量级,代价是段内差异被平均掉,段内冷热不均仍然存在。
  • 区域级:以更大的区域(如若干段组成的大区)为记账单位。表最小,适合超大容量器件,只能保证区域之间的大致均衡。
粒度记账条目量级能识别的差异表规模迁移代价典型适用
页级页数量级块内页间极大低块内写指针轮转
块级块数量级块间中中主流器件
段级段数量级段间小中到高大容量与嵌入式控制器
区域级区数量级区间很小高超大容量、内存受限

选择粒度的经验规则是:在内存与表规模允许的范围内,尽量选最细的一档。因为粒度一旦选粗,段内/区内的差异就永久性地看不见了,后面再怎么调参数都补不回来。反过来,粒度选细带来的表规模压力,可以通过压缩计数位宽、分层记账(粗粒度常驻内存、细粒度按需加载)来缓解,这属于可实现性问题,而不是原理性障碍。

粒度选错的两类典型症状

症状一:粒度选得太粗。表现为表很小、内存很松,但极差长期压不下去,且怎么调参数都改善有限。原因是段内或区内的差异根本看不见,算法无从下手。这种情况下调参数没有用,只能把粒度做细。

症状二:粒度选得太细。表现为均衡效果不错,但内存吃紧、掉电保存时间变长、极端情况下出现换入抖动。这种情况下可以考虑分层记账:粗粒度常驻、细粒度按需,而不是简单地把粒度整体调粗——后者会把已经获得的均衡能力一起丢掉。

粒度越粗,表越小、迁移越少,但能达成的均衡度越低页级以页为记账单位块内页间轮转不解决块间差异表规模可达均衡度反向指标块级以块为记账单位主流粒度表规模与块数成正比表规模可达均衡度反向指标段级以块组为记账单位表缩小一个量级段内差异被平均掉表规模可达均衡度反向指标区域级以大区为记账单位表最小只保证区间均衡表规模可达均衡度反向指标读法:表规模条越长表示表越大;可达均衡度条越长表示理论上能摊得越均匀。两组长条方向相反 —— 粒度细化把均衡度推上去的同时,也把表规模与迁移量一起推上去。示意图:条长为定性对照,不构成任何具体实现的比例关系。
图 4 · 均衡粒度四档:页 / 块 / 段 / 区域的表规模与可达均衡度对照

3. 动态磨损均衡

动态均衡是三层算法里最轻的一层,也是唯一不产生任何额外数据搬迁的一层。它的全部动作只有一句:当需要一个新的空闲块来承接写入时,从空闲块池里挑擦除计数最低的那一个。这一章讲它的原理、实现结构、效果边界、代价与适用场景——重点是它的失效场景,因为那正是静态均衡存在的理由。

3.1 原理:只挑擦除计数最低的空闲块

动态均衡的工作时机非常明确:分配新块的那一刻。平时它什么都不做,不扫描、不统计、不搬迁。

它的判定规则也只有一条:在当前空闲块池里,比较各块的擦除计数,取最小的那个分配出去。这条规则的效果是——计数低的块会被优先用起来,计数高的块会在池里多待一会儿,于是各块的使用机会被拉平。

理解这条规则,有两个关键词必须抓住:

  • 关键词一:被动。它只在「需要新块」时被触发。没有写入、没有回收、没有开新块的需求时,它完全不动。
  • 关键词二:候选集只有空闲块。这是它的力量所在,也是它的致命限制:已经存放着数据的块(尤其是冷数据块)永远不在候选集里,因此永远不会被它选中、不会被它腾挪。

从效果上看,动态均衡解决的是「新写入往哪放」的问题,不解决「已经放好的数据要不要动」的问题。前者是分配问题,后者是布局问题,两者的难度完全不同。

要素动态均衡的做法带来的结果
触发时机需要分配新块时完全被动,无空闲调度开销
候选集仅空闲块池已占用块不参与,冷端不受影响
比较依据块的擦除计数计数低的优先被用
是否搬迁数据不搬迁不产生额外写入
是否修改映射不改已有映射无额外映射更新开销
是否额外擦除不额外擦除不额外消耗寿命
实现复杂度低小容量器件也能做

3.2 实现结构:有序链表与最小堆

原理只有一句话,但要做得快,需要一个合适的数据结构。核心操作是三个:取计数最小的块(分配时)、块计数加一后重新归位(擦除后)、新块加入池(回收后)。

常见的三种实现结构各有取舍:

结构取最小更新位置插入内存开销适合场景
无序数组 + 线性扫描线性级常数级常数级最小块数很少、分配不频繁
按计数分桶的链表数组接近常数级常数级常数级中等,随计数档位数增长计数范围有限、档位可枚举
最小堆常数级取堆顶对数级对数级小,一个数组即可块数多、分配频繁
平衡二叉搜索树对数级对数级对数级较大,有指针开销需要同时支持范围查询

工程上最常见的组合是「分桶链表 + 少量堆」:把擦除计数按档位分桶(例如每若干次一档),每个桶挂一条空闲块链表;分配时从最低的非空桶取头节点,块计数加一后挂到新档位的桶尾。这种结构的优点是三个核心操作都接近常数时间,且不需要为每个块维护指针节点,内存开销可控。缺点是桶内不做排序,同一档位内的块按挂入顺序使用,牺牲了一点精度换来了实现简洁。

需要更高精度时,可以在桶内再挂一个小顶堆,或者把档位做细。代价是内存与维护复杂度上升。

实现时最容易踩的坑

把擦除计数当作「每次擦除就无条件加一」来维护是不够的。至少要处理三件事:一、计数必须持久化,掉电后要能恢复,否则整张表失真;二、计数的更新必须与擦除动作原子绑定,擦除成功才加,失败不加;三、替换块与坏块要从候选集里剔除,否则会挑到不可用块。这三件事里任何一件出错,都会让算法「看起来在跑,实际上在乱跑」。

3.3 效果边界与失效场景

动态均衡的效果边界,完全由它的候选集决定。把它能覆盖与不能覆盖的范围列清楚:

场景动态均衡是否有效原因后果
写入均匀分布有效各块被轮到的机会接近计数分布保持紧凑
热点集中在少数逻辑区部分有效热端在空闲池内被轮转热块被摊开,但仍领先
存在大量只读冷数据基本无效冷块不在候选集,永不参与冷端计数长期停在低位
容量接近写满效果下降空闲池小,可选范围窄轮转空间被压缩
写入量极小看不出效果总擦除次数本来就少不做也无妨
一次性写入后长期静置完全无效没有新分配动作发生分布定格在写入时的形态

把这些场景归纳成一句话:动态均衡只对「被写进去的数据」有效,对「已经躺在里面不动的数据」无效。第 1.2 节说过,冷数据往往占容量的大头——这就意味着动态均衡在最需要起作用的那部分容量上,恰恰完全不起作用。

这是它最大的失效场景,也是最容易被误判的场景:因为从外部看,动态均衡一直在工作(分配、计数更新、空闲池轮转都在跑),所有可观测的动作都正常,但冷端与热端的差距仍在持续拉大。「算法在跑」不等于「算法有效」,这个区别在第 10 章会再展开。

动态均衡的全部动作:只在「需要新块」的那一刻,挑擦除计数最低的空闲块写入请求到达逻辑地址需要落盘需要空闲块写指针耗尽或需开新块查计数表挑最低只在空闲块池内比较分配并写入该块擦除计数加一这条链路的三个特征特征一 · 被动只在需要新块时触发,不主动找活干特征二 · 范围有限候选集只有空闲块,不含已占用块特征三 · 代价极低不产生任何额外数据搬迁天生零迁移挑哪个块都不多写一笔管不住冷端冷数据块不在候选集里对写入集中有效热端轮转效果明显示意图:四个环节为逻辑抽象,实际实现常与写指针、垃圾回收合并执行。
图 5 · 动态均衡的选块流程:被动触发、只在空闲块池内比较、零额外搬迁
冷数据块被永久锁定:动态均衡的候选集里从来没有它们块阵列:冷端占多数却从不参与,热端占少数却被反复擦写冷端:计数长期不变热端:计数持续冲高动态均衡只在热端与空闲池之间循环冷端不参与任何一次分配决策结果:冷端与热端的计数差距随时间单调拉大,直到热端先触顶看不见冷块从未进入候选集搬不动动态均衡不产生搬迁救不了只能靠静态均衡补位示意图:块阵列为定性示意,冷热块的分布形态随负载而定。
图 6 · 动态均衡最大的失效场景:冷数据块被永久锁定在低位计数上

3.4 代价分析

动态均衡的代价在三层算法里是最低的,但并不是零。把它的代价拆成三项来看(沿用第 2.2 节的框架):

代价项动态均衡的表现说明
迁移写入基本为零它只改变「新数据写到哪」,不搬动已有数据
表空间需要整张擦除计数表块级记账,条目数与块数同量级
擦除成本不额外增加擦除次数由写入量决定,与挑哪个块无关
额外开销每次分配多一次比较分桶或堆结构下开销很小
掉电保护开销计数表需持久化这是主要的实现代价

换句话说,动态均衡的代价主要是一次性的实现代价(一张计数表 + 一个有序结构 + 持久化机制),而不是持续的运行代价。一旦实现完成,它运行起来几乎不增加 NAND 侧写入。这也是为什么它几乎是所有带控制器的存储器件的标配——投入产出比太高了,不做反而奇怪。

但正因为它便宜,也容易出现「只做动态均衡就以为万事大吉」的误判。这个误区在第 10.1 节单独讨论。

3.5 适用场景

动态均衡适合以下几类情况,判断标准是冷数据占比低、或者总写入量相对容量很小:

适用情况判断依据理由
小容量器件,写入量相对充足总写入次数远未接近耐久上限不做均衡也够用,做了更稳
数据基本都会周期性更新冷数据占比低动态轮转已能覆盖大部分块
内存与算力严重受限无法承受搬迁与复杂表动态均衡是唯一可选项

另有两类情形不列入上表:「只读或近只读场景」的写入集中在初始化阶段,分布定格,动态均衡无从发挥,属于不适合的情形;「作为其他均衡的基础层」则不是独立适用项——动态层负责分配,上层机制负责布局。

一句话定位

动态均衡是必要条件,不是充分条件。任何一套完整的磨损均衡都应该包含它(因为它的代价极低、收益确定),但任何一套只有它的方案,在存在大量冷数据的场景里都会失效。判断是否需要往上加一层,看的是「冷数据占多少」而不是「写入有多热」。

最后补一条经常被问到的实务问题:动态均衡会不会让性能变差?答案是基本不会。它只在分配时刻多一次比较,而比较的代价在分桶或堆结构下极小;它不改变写入路径的长度,也不产生额外 I/O。因此如果发现开启动态均衡后性能明显下降,问题大概率不在均衡本身,而在计数表的持久化策略——比如每次擦除后都立刻写一次元数据到 NAND,那就把一次内存操作变成了真实写入。这类开销属于实现问题,可以通过延迟合并提交来消除。

4. 静态磨损均衡

静态均衡是三层算法里唯一主动制造数据搬迁的一层。它的核心动作是:把擦除计数低的块上存放的冷数据,搬到擦除计数高的块上,从而把低计数块腾出来交给热数据使用。这一章讲它的原理、冷数据怎么识别、什么时候触发、搬多少、以及它带来的新风险。核心权衡一句话:用额外的迁移写入,换更高的均衡度。

4.1 原理:主动搬迁低磨损块上的冷数据

先解释「静态」这个名字:它指的不是「静态数据」,而是「让静态(不常变)的数据也参与进来」。这一点经常被读反。

它的操作方向值得特别说明,因为很容易搞反:

  • 源块是擦除计数低的块(上面放的是冷数据,所以计数低)。
  • 目标块是擦除计数高的块(它已经被磨得比较多了)。
  • 搬迁之后:冷数据被放到高计数块上(冷数据在写入后不再改动,放上去之后这块就不会继续被磨),而腾出来的低计数块被回收进空闲池,接下来会被热数据优先使用。

于是发生了一次「交换」:冷数据替热数据承担了已经消耗掉的那部分磨损,热数据拿到了新鲜的块。从整盘看,冷端计数被抬起来,热端计数上升变慢,极差被压缩。

这个交换之所以成立,靠的是冷数据的性质——它搬过去之后不会再被频繁改写。如果把热数据搬到高计数块上,等于把最热的数据放到最旧的块上,是纯粹帮倒忙。

环节选谁判据做错会怎样
源块低擦除计数且存冷数据的块计数低 + 长时间无改写误搬热数据会打断业务写入
目标块高擦除计数的块计数高于均值一定幅度选到中位块则收益很小
搬迁内容源块上的全部有效页有效页位图漏搬会造成数据丢失
搬迁后源块擦除后进入空闲池无有效页残留残留旧页会占位
映射更新逻辑地址改指新物理块地址映射表漏改会读到旧位置的废数据

4.2 冷数据的识别方法

静态均衡成败的关键,几乎全在「什么叫冷」这个判定上。判错了,搬的就是热数据,代价付了收益没有。

常见的识别方法按信息源分成三类:

方法依据优点缺点适用
最后写入时间距上次写入的时间长度实现最简单,一个时间戳无法区分「写了很久但马上要热」粗判,作为前置过滤
窗口内改写次数固定时间窗口内的改写次数能反映近期活跃度窗口长度敏感,需调参主流做法
逻辑地址热度表按逻辑区间统计访问频率与业务语义相关性好需要额外表与维护开销控制器有能力时
主机显式提示主机告知哪些数据为冷最准确需要接口支持,通用性差有专用接口时
推断式标记结合写入大小、对齐、地址分布不需要额外接口误判率较高作为辅助信号

工程上最常用的是窗口内改写次数:给每个块(或每个逻辑区间)维护一个计数器,在一个滑动窗口内统计被改写的次数,次数低于阈值的判为冷。窗口长度与计数阈值是两个需要调的参数,见第 8.4 节。

还需要一个容易被忽略的补充判据:块的擦除计数本身。一个块如果计数很低且被判定为冷,它是理想的搬迁源;但如果一个块计数很低却判定为热,说明它只是刚被换上来的新块,不应该马上搬走。因此实际的源块选择通常是两个条件的交集:计数低于某个下限,且冷度高于某个门槛。

4.3 触发时机与阈值

静态均衡不能一直跑(代价太高),也不能不跑(冷端锁死)。触发时机的设计就是在这两者之间找节奏。

触发方式判据优点缺点典型适用
极差触发最高计数与最低计数之差超过阈值直接对准目标指标对个别异常块敏感通用
离散度触发标准差与均值之比超过阈值反映整体分布计算量略大有统计能力时
冷端占比触发低计数块占比超过阈值直接暴露静态均衡的必要性依赖冷热定义冷数据明确的场景
周期性触发每隔固定时间或固定写入量执行一次节奏可控,便于预算可能与负载不同步负载平稳时
空闲窗口触发检测到空闲时段就执行一批不影响前台性能空闲不足时会被饿死有明显空闲的设备
寿命预警触发最高计数接近耐久上限一定比例风险导向,优先级最高触发时可能已经偏晚作为兜底触发

实际系统往往是「周期 + 条件」的组合:每隔一段时间检查一次,只有当条件(极差或离散度)成立时才真正执行搬迁。这样既避免了无意义的搬迁,也避免了条件长期成立却一直不动作。

阈值怎么定,见第 8.1 节。这里只给一个方向性建议:触发阈值应该以「距离耐久上限还有多少」为锚,而不是以绝对值。同样的极差,在寿命早期无所谓,在寿命后期就是要命的。

4.4 迁移量的代价

静态均衡的代价是每次搬迁都要真金白银地写一遍。一次搬迁的完整开销包括:

开销项是什么与什么成正比能否优化
读出源块有效页把源块上还有效的数据读出来源块有效页数量能,选有效页少的块做源
写入目标块把读出的数据写进目标块有效页数量不能,是物理必需
擦除源块腾空源块以便复用搬迁次数能,与回收合并执行
更新映射逻辑地址指向新位置搬迁页数能,批量提交
更新计数与冷热表维护元数据搬迁块数能,批量提交
掉电保护写入把上述变更持久化变更条目数部分能,合并日志

把这些开销折算成写放大系数的增量,是评估静态均衡代价最实用的方法:把一段时间内的搬迁写入量,除以同一段时间内的主机写入量,就得到均衡带来的写放大增量。经验上,一个调得比较好的静态均衡,这个增量应该明显小于 1;如果做到 1 以上,说明搬得太凶,需要收敛。

控制迁移量的三个主要手段:

  • 限批量:每次触发只搬固定数量的块,剩下的等下一次。这是最直接有效的手段(见第 8.2 节)。
  • 挑有效页少的源块:源块上有效页越少,读出与写入的量越小。优先搬那些「大部分页已经失效、只剩少量有效页」的冷块。
  • 与垃圾回收合并:如果某个块本来就要被回收,顺手把它的有效页搬到高计数块上,一次擦除服务两个目的(见第 5.3 节)。

这三个手段里,「挑有效页少的源块」最容易被忽略,但收益往往最明显。原因是搬迁成本几乎全部由有效页数决定:一个只剩几页有效数据的冷块,搬起来几乎不花钱;而一个装满有效数据的冷块,搬一次等于重写一整个块。因此源块选择应该把「有效页数少」作为首要排序键,把「冷度」与「计数低」作为过滤条件,而不是反过来。很多迁移量居高不下的案例,根子就在这个排序键上。

4.5 效果与风险

静态均衡把均衡度推上一个台阶,但也引入了一组动态均衡没有的风险。这些风险不是「实现不好才会有」,而是机制本身自带的,只能通过参数与工程手段压制,不能根除。

风险机理表现缓解手段
误搬热数据冷热判定出错刚搬走又被改写,双重写入加窗口、加确认期、搬后观察
搬迁抖动同一批数据被反复搬来搬去迁移量居高不下,均衡度不改善搬迁后设冷却期,禁止短期内再选为源
写放大恶化搬迁量占比过高NAND 侧写入远超主机侧限批量、与回收合并
前台性能抖动搬迁占用带宽与擦除时间偶发长尾延迟放到空闲窗口,降低单次批量
掉电一致性风险搬迁中途掉电源块与目标块状态不一致原子提交、日志、可回滚
计数表失真计数更新与擦除不同步均衡基于错误信息决策原子绑定、掉电恢复校验
静态均衡最危险的一种失效

不是「搬得不够」,而是「搬了但搬错了」。搬错比不搬更糟:不搬只是冷端继续锁死,寿命按原样走;搬错则同时付出迁移写入的代价,又没有换来任何均衡收益,甚至因为把热数据放到高计数块上而加速了热块的磨损。因此冷热判定的准确度,比搬迁的执行效率更重要——宁可搬得慢,不可搬得错。

静态均衡的五个动作:主动制造一次搬迁,把冷数据从低计数块挪到高计数块阈值触发极差越过门槛选源块低计数的冷块选目标块高计数的块搬迁数据读出再写入回收与记账旧块擦除入池一次搬迁要付的账账一 · 读出再写入源块整块有效页读出,写入目标块这部分写入主机完全感知不到账二 · 映射要改逻辑地址必须指向新的物理位置这部分写入主机完全感知不到账三 · 旧块要擦擦除本身又消耗一次寿命预算这部分写入主机完全感知不到换来了什么冷端开始参与磨损付出了什么额外迁移写入与擦除关键是批量搬多少决定代价大小示意图:五个动作在真实实现中常与垃圾回收合并,以减少重复读出与擦除。
图 7 · 静态均衡的冷数据搬迁流程:主动把冷数据从低计数块挪到高计数块