HOOOS

LSM 存储引擎高频写入时 Leveled 与 Universal 的动态写放大波动曲线有什么本质区别

0 10 存储架构师 LSM-TreeRocksDB存储引擎
Apple

在基于 LSM-Tree(Log-Structured Merge-tree)架构的存储引擎(如 RocksDB、TiKV 等)中,**写放大(WAF - Write Amplification Factor)**是决定系统写入吞吐量和 SSD 寿命的核心指标。

在高频持续写入的极端场景下,**Leveled Compaction(分层压实)**与 Universal Compaction(通用/大小分级压实)展示出了截然不同的动态 WAF 波动曲线。这两者不仅在平均 WAF 数值上有数倍的差距,其随时间推移的波动形态、I/O 抖动特征以及背后的物理机制更是有着本质的不同。


1. 动态 WAF 波动曲线的直观对比

如果我们将高频写入过程中的“瞬时 WAF”(例如以 10 秒为窗口计算的物理写字节数 / 用户写入字节数)绘制成曲线,会看到以下特征:

WAF 值
  ^
  |      Universal Compaction (巨幅锯齿波 / 周期性尖峰)
  |          /\                /\                /\
  |         /  \              /  \              /  \
  |        /    \            /    \            /    \
  |_______/______\__________/______\__________/______\____
  |
  |      Leveled Compaction (高位窄幅脉冲 / 相对平稳)
  |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (均值较高)
  |_______________________________________________________
  +---------------------------------------------------------> 时间 (持续高频写入)

Leveled Compaction:高位窄幅微波线

  • 均值特征:WAF 长期维持在较高水平(通常在 10 到 30 之间,取决于层数和放大因子)。
  • 波动特征:曲线呈现高频、窄幅的微小波动。没有极端的波谷,也没有高出均值数倍的巨型尖峰,整体表现为一条高位“毛刺带”。

Universal Compaction:低位宽幅巨齿波

  • 均值特征:WAF 长期均值极低(通常在 2 到 8 之间)。
  • 波动特征:曲线呈现极低基线与超大周期性尖峰交替的形态。在绝大部分时间内,WAF 趋近于 1(只写 WAL 和 L0);但每隔一个固定周期,WAF 会瞬间飙升至数倍甚至数十倍于均值的尖峰,随后断崖式下跌,形成“过山车”式的剧烈抖动。

2. 波动曲线差异的底层物理机制

要理解这两条曲线为什么长成这样,需要深入到两者的 Compaction 触发机制和执行粒度。

Leveled Compaction 的“渐进式小步快跑”

Leveled Compaction 将数据严格划分为 $L_0, L_1, L_2, ..., L_n$ 层。除了 $L_0$ 之外,每一层内部的数据都是全局有序且不重叠的。

L1: [  A-D  ] [  E-H  ] [  I-L  ]
         \         /
          \       /  (合并重叠键范围)
           v     v
L2: [A-B] [C-D] [E-F] [G-H] [I-J] [K-L]

当 $L_i$ 层的大小超过设定的阈值(通常每层是上一层的 10 倍)时,会触发 Compaction:

  1. 局部性合并:它不会把整层数据拿来合并,而是从 $L_i$ 中挑出一个 SST 文件,找出它在 $L_{i+1}$ 中所有有 key 范围重叠的 SST 文件,进行多路归并排序。
  2. 写放大的分摊:因为每次只合并一小部分文件(通常是 1 个上层文件合并到 10 个下层文件),单次 I/O 任务量是受限且可控的。
  3. 多层流水线并发:在高频写入下,从 $L_0 \to L_1$,$L_1 \to L_2$,$L_2 \to L_3$ 的合并几乎是同时、并发、不间断地在后台发生的。
  • 本质原因:Leveled 的 WAF 是在空间上离散、在时间上连续分摊的。高频写入时,后台始终有大量的、小规模的“局部合并”在运转。因此,它的动态 WAF 曲线没有空闲期,始终维持在高位,但由于单次合并规模小,曲线极度平稳。

Universal Compaction 的“隐忍与全量爆发”

Universal Compaction(类似于 Size-Tiered)不保证层与层之间的 key 不重叠。它更像是一个“攒文件”的过程。所有的 SST 文件(或 Sorted Runs)按照时间顺序或大小排列。

[Run 1 (小)] [Run 2 (小)] [Run 3 (中)] [Run 4 (大)]
   \           /
    v         v
[  New Run 1-2  ] (条件触发:Size 相似或文件数超限)

它的触发主要基于三个启发式条件:

  1. 空间放大率超限(Size Amplification):当系统整体大小超过一定比例,触发全量合并(Full Compaction)。
  2. 文件数量超限(Individual Size Ratio):当排在前面的小文件数量太多,或者大小比例满足特定算法时,将这些小文件合并为一个大文件。
  3. 绝对文件数限制(Num Files Limit)。

在中高频写入时:

  • 平静期(WAF $\approx$ 1):数据源源不断地写入 MemTable 并 Flush 成 $L_0$ 的小文件。在没有触发 Compaction 阈值前,系统几乎没有后台 I/O。此时 WAF 的测量值极低。

  • 爆发期(WAF 暴涨):一旦文件数或大小比例触发了临界点,系统必须把积攒的一堆 SST 文件(在极端情况下甚至是全部文件)读入内存进行一次全量的归并排序,写回磁盘。

  • 本质原因:Universal 的 WAF 是在时间上离散、在单次任务中高度集中的。它平时不干活,一干活就是“移山填海”式的全局大合并。因此,动态 WAF 会在瞬间拉出一个巨大的电击样尖峰。


3. 伴随现象:对系统吞吐与 Write Stall(写入停顿)的影响

动态 WAF 波动曲线直接映射到了存储引擎的吞吐稳定性和延迟表现上。

指标 Leveled Compaction Universal Compaction
平均吞吐量 较低(因为 I/O 资源长期被 Compaction 侵占) 较高(总的 WAF 低,SSD 写入带宽被充分留给用户)
P99 写入延迟 相对稳定,不易出现极端长尾延迟 存在严重的周期性毛刺,P99 和 P999 延迟极高
Write Stall 触发特征 渐进式限速。由于 L0 堆积或某层 Pending Bytes 缓慢上升,写入速度平缓下降 突发性卡死。当全量 Compaction 霸占全部 I/O 带宽时,MemTable 来不及 Flush,直接触发 Hard Stall,写入完全锁死

Leveled 的 Write Stall:

Leveled 的限速算法(Rate Limiter)更容易平滑介入。因为它的后台 Compaction 压力是连续递进的,系统可以预测出“写入速度即将超过合并速度”,从而在用户侧进行微调限速(如将 100MB/s 限制到 80MB/s),曲线表现为平滑的降速。

Universal 的 Write Stall:

Universal 的 Stall 是“断崖式”的。在进行大规模或全量 Compaction 时,磁盘 I/O 被瞬间吃满。此时如果高频写入继续,L0 文件数会瞬间暴增,直接撞上 level0_slowdown_writes_trigger 甚至 level0_stop_writes_trigger 阈值,用户端感受到的就是系统突然“卡死”几秒甚至几十秒,等大合并结束后又瞬间恢复。


4. 生产环境如何根据 WAF 曲线进行技术选型?

在实际架构设计中,不能单纯因为 Universal 的平均 WAF 低就盲目选择它。必须结合 WAF 动态曲线的特征来做决策。

适用 Leveled Compaction 的场景

  1. 对延迟敏感的在线业务(OLTP):如用户交易、实时社交、即时定位等。这类业务宁可整体吞吐低一点,也绝不能接受 P99 延迟偶尔飙升到几秒。Leveled 稳定的 WAF 曲线能保证 SLA 指标的平滑。
  2. 读多写少或读写均匀的场景:Leveled 因为每一层无重叠,读放大(RAF)和空间放大(SAF)都极低,配合其稳定的 WAF,是通用数据库的最佳选择。

适用 Universal Compaction 的场景

  1. 极高频的纯写入/归档场景(Write-Heavy):如时序数据收集(IoT 传感器、监控 Metrics 汇聚)、应用日志收集、历史数据备份。
  2. 对 SSD 寿命极度敏感的硬件环境:如果在廉价消费级 SSD 上部署,Leveled 长期高位的 WAF 会迅速耗尽 SSD 的 PE 次数(写入寿命),而 Universal 可以延长数倍的硬件寿命。
  3. 大批次导入(Bulk Load):离线计算完一批数据,一次性灌入引擎,允许在非业务高峰期执行全量 Compaction。

总结

Leveled 与 Universal 在高频写入下的 WAF 曲线差异,本质上是**“用空间和读性能的妥协换取时间上的平滑(Leveled)”,与“用暂时的空间混乱和周期性延迟抖动换取物理写入极小化(Universal)”**两种哲学对立的结果。在系统调优时,观察 WAF 曲线的波动形态,往往比单纯看一个平均 WAF 数值,更能揭示系统潜在的性能瓶颈。

点评评价

captcha
健康