LSM Compaction 调优:写放大不是一个参数能解决

LSM Compaction 调优:写放大不是一个参数能解决

一、LSM 的性能账要长期算

LSM Tree 通过顺序写和后台 compaction 提升写入性能,广泛用于 RocksDB、LevelDB 和很多分布式存储系统。但 LSM 的代价也很明确:写放大、读放大、空间放大和后台任务抖动。调优时如果只看前台写入 QPS,迟早会被后台 compaction 找回来。

Compaction 的目标是把多层数据整理合并,清理过期版本,降低读放大。但它会消耗 CPU、磁盘 IO 和带宽。当前台写入高峰与后台 compaction 抢资源时,延迟会出现明显抖动。调优不是关闭 compaction,而是让它和业务负载形成稳定平衡。

二、LSM 层级:写入快,整理慢

flowchart TD A[写入 MemTable] --> B[Flush SSTable] B --> C[L0 Files] C --> D[Compaction 到 L1] D --> E[Compaction 到 L2] E --> F[更低层数据] C --> G[读放大]

L0 是最敏感的层级。L0 文件过多会增加读放大,也可能触发写入停顿。很多系统的写延迟尖刺,都能在 L0 文件数、pending compaction bytes 和磁盘带宽中找到证据。看不到这些指标,只看业务延迟,就是闭眼开车。

写放大和空间放大通常相互牵制。更激进的 compaction 能降低读放大和空间占用,但会增加写放大;放松 compaction 能提高短期写入吞吐,但会堆积后台债务。调优必须结合读写比例、数据更新频率和存储介质能力。

三、配置示例:先让指标可观察

下面是一组常见监控指标名称示例。不同系统命名不同,但含义相近。

lsm_metrics: - l0_file_count - pending_compaction_bytes - write_stall_micros - compaction_read_bytes - compaction_write_bytes - block_cache_hit_rate - read_amp_estimate

调优前先建立基线。记录正常流量下的写入 QPS、P99 延迟、L0 文件数、compaction 带宽、cache 命中率和磁盘利用率。没有基线,就无法判断参数调整是优化还是把问题推迟。

如果写入周期性抖动,可以检查 compaction 是否和业务高峰重叠。可以限制后台 compaction 带宽,或者在低峰期提高整理速度。但限制过低会积累债务,低峰期补不回来。参数要看长期曲线,不能只看改完一小时。

四、调优边界:负载模型决定策略

写多读少场景更关注写入停顿和空间放大;读多写少场景更关注读放大和缓存命中;大量更新删除场景更关注过期版本清理。不同负载下,compaction 策略不同。把别人的 RocksDB 参数复制过来,通常只能复制事故概率。

存储介质也影响策略。SSD、NVMe 和云盘的随机读写、带宽和延迟差异明显。云盘还可能有突发积分和带宽上限,compaction 抢满 IO 后,业务读写会一起变慢。调优报告必须写清硬件和云盘规格,否则结论没有迁移价值。

最后要压测长时间稳定性。LSM 系统短压测很容易好看,因为后台债务还没积累。至少要跑到数据量超过内存、经历多轮 compaction,并观察延迟尾部。存储系统调优,短跑成绩说明不了马拉松表现。

五、总结

LSM Compaction 调优要同时看写放大、读放大、空间放大和后台资源争用。L0 文件数、pending bytes、write stall 和 compaction IO 是关键证据。参数没有通用答案,只有和负载、硬件、数据生命周期匹配的平衡点。