存储 Compaction 任务如何调度?
简化版
Compaction 调度要在“及时清债”和“不抢前台资源”之间平衡:按 L0 文件数、重叠率、墓碑比例、空间回收收益和 backlog 给任务排序,限制每节点并发、磁盘带宽与 CPU;Flush 通常优先于普通 Compaction。积压接近写停顿阈值时再动态加速,不能只靠固定定时任务。
详细版
Compaction 会读多个旧文件、归并并写新文件,消耗读写带宽、CPU 和临时空间。跑得太慢会增加读放大、空间放大和 L0 文件数,最终触发写 stall;跑得太快又会抬高前台 P99。
调度器通常先挑选候选:L0 重叠严重、层级大小超标、墓碑可释放空间多、TTL 到期或手工 repair。再按收益/成本打分,并检查磁盘水位、目标层空间和并发冲突。
例如磁盘可稳定提供 800 MB/s,前台峰值需 500 MB/s,可先给后台 150 MB/s、保留 150 MB/s 安全余量;backlog 持续增长时提升后台额度,前台 P99 超标时回落。
任务必须支持取消、续跑和原子提交。生成的新 SSTable 未完成校验并更新 manifest 前,旧文件不能删除。
完整版教学
一、Compaction 是后台债务
LSM 把前台写入变成 WAL、MemTable 和顺序 Flush,但会留下重叠 SSTable、旧版本与墓碑。Compaction 负责归并排序、消除覆盖版本并维持层级约束。它不运行时前台一开始可能更快,随后读放大和空间占用不断恶化。
二、任务从哪里产生
不同触发器代表不同风险。L0 文件过多会让读请求检查大量文件,也可能达到硬写停顿;层级超容量会扩大重叠;墓碑密集文件具有较高回收收益;TTL 文件若可整段删除,则不必做昂贵全量归并。
| 触发器 | 优先原因 | 常用指标 |
|---|---|---|
| Flush/L0 压力 | 直接威胁写入 | L0 file count |
| 层级超标 | 维持 size ratio | level bytes / target |
| 墓碑回收 | 释放空间 | stale ratio |
| 手工 repair | 修复数据 | repair urgency |
三、如何给候选任务打分
可把紧迫度、读放大收益、可释放字节与预计 I/O 成本组合评分。评分不是固定公式,关键是避免只按文件年龄 FIFO,导致一个巨大低收益任务堵住小而紧急的 L0 任务。
score = urgency_weight * threshold_ratio
+ read_gain + reclaim_gain
- io_cost - overlap_conflict
调度还要检测 key range 冲突。同一层或相邻层的两个任务若同时改写重叠范围,会增加同步复杂度或重复工作,通常应串行或使用明确锁定区间。
四、资源控制与数字例子
假设 NVMe 顺序吞吐 800 MB/s,前台峰值读写消耗 500 MB/s,不能把剩余 300 MB/s 全给 Compaction,因为突发和 fsync 还需余量。初始限额可设 150 MB/s,并根据 P99、队列深度和 backlog 做反馈控制。
并发数也不是越高越好。两个任务各 150 MB/s 可能已打满后台预算,开到八个只会增加随机 I/O 和上下文切换。机械盘、云盘和 NVMe 的最优配置完全不同,必须压测。
五、动态加速与写停顿
当 pending compaction bytes 的增长率长期高于完成率,债务会无限积累。调度器可分 soft limit 和 hard limit:soft limit 开始限写并提高后台资源,hard limit 触发写 stall,防止 L0 和空间失控。
这不是性能 bug,而是保护机制;但频繁 stall 说明容量或调度失衡。告警应看“预计多久触达 hard limit”,而不是等 stall 已发生才通知。
六、任务提交与故障恢复
Compaction 先写临时 SSTable,完成 checksum、索引和 fsync,再通过 manifest/版本编辑原子发布,最后删除不再被引用的旧文件。进程中途崩溃时,未发布输出可安全回收,旧版本仍可读。
监控包括 pending bytes、各层 score、吞吐、读写字节、write amplification、任务耗时、取消次数、临时空间、stall 秒数和前台 P99。租户系统还要防单租户大任务占满全局后台预算。
记忆钩子:Compaction 调度不是“有空就跑”,而是给存储债务排优先级、定还款速度,并保证还债时不让前台断粮。
七、常见误区与追问
- 误区:暂停 Compaction 能长期提升写性能。 它只把成本延期,最终会以读放大和写停顿偿还。
- 误区:并发越多 backlog 越快清空。 超过磁盘能力后只会增加竞争和尾延迟。
- 误区:所有 Compaction 同优先级。 Flush/L0 压力通常比普通空间整理更紧急。
- 追问:为何需要临时空间? 新文件发布前旧文件仍被读者引用,二者会短时共存。
- 追问:如何避免影响前台? 带宽/并发限额、反馈控制、错峰和租户配额共同约束。
- 追问:何时允许写 stall? 接近硬安全边界时作为最后保护,同时必须告警和扩容。
八、加强记忆
调度顺序是“先识别债务,再评估收益成本,然后受资源预算约束执行”。Flush 和 L0 关系到写入生死,普通层级整理关注读写空间放大;动态限速用前台 P99 与 backlog 双反馈,原子发布保证任务失败不会破坏现有可读版本。