Appearance
RocksDB 核心原理:从 MemTable 到 Compaction
原文发布:2026-06-11 · 最后核对:2026-10-12
修订说明:原文把 WAL 写入等同于已经落盘,并断言 LSM 读一定比 B+ Tree 慢。这两处说法忽略了配置和负载条件,现已更正。随笔分类里的同题页已合并到此页,旧地址仍可访问。
RocksDB 是嵌入式键值存储引擎库。应用通过 Get、Put、Delete 和迭代器操作它,不需要为了引擎本身单独部署一个网络服务。它把数据按键排序,核心结构包括 MemTable、SST 文件和日志文件。RocksDB 的官方概览介绍了这些结构。
一次写入经过什么
通常情况下,写入会进入内存中的 MemTable,并写入预写日志(WAL)。当 MemTable 达到配置条件,后台把它刷成有序的 SST 文件。大致路径如下:
text
Put(key, value)
├─ WAL(可按配置启用、同步或关闭)
└─ MemTable
└─ Flush → L0 SST
└─ Compaction → 更深层级写入返回不一定代表机器断电后仍可恢复。 RocksDB 文档说明,默认非同步写入可能还停留在操作系统缓冲区;若需要每次写入都等待持久化介质,应按需求使用同步写入,并理解由此增加的延迟。关闭 WAL 的写入在进程崩溃时也可能丢失。具体语义见官方 Basic Operations和WAL 文件说明。
一次读取经过什么
读取先检查 MemTable,再查找可能包含目标键的 SST 文件。在常见的分层压缩配置中,L0 文件的键范围可能互相重叠;更深层级的同层文件通常不重叠。索引、Bloom Filter、Block Cache 和操作系统缓存可以减少无用读取。
因此不能简单说“RocksDB 读比 B+ Tree 慢”。读延迟受键分布、缓存命中、L0 文件数量、压缩方式、存储设备和查询类型影响。点查和范围扫描也不应合并成一个性能数字。RocksDB 的调优指南建议从读放大和缓存命中等指标定位瓶颈。
Compaction 为什么重要
Flush 会不断产生新的 SST 文件。Compaction 在后台合并有重叠范围的文件、整理版本与删除标记,让读取路径保持可控。它也会读写额外的数据,因此存在三种相互牵制的成本:
| 指标 | 关注什么 |
|---|---|
| 读放大 | 一次查询需要检查多少文件或读取多少数据 |
| 写放大 | 用户写入一份数据,存储设备实际写了多少份 |
| 空间放大 | SST、旧版本和压缩临时空间占用多少额外容量 |
不同 Compaction 策略会改变这些成本的平衡。分层压缩通常有利于点查,但可能增加后台写入;其他策略可能减少写放大,却增加读放大或空间峰值。应按业务写入速率、点查/扫描比例和磁盘空间测试,而非照搬一组“万能参数”。见官方 Compaction 介绍与调优指南。
上线前测什么
- 明确写入确认需要的持久性保证,并用进程崩溃、机器重启两种测试分别验证。
- 分别测点查、范围扫描、批量写入和混合负载,不用单一平均延迟代表整体性能。
- 观察 L0 文件数量、Flush/Compaction 积压、P95/P99 延迟、写放大和磁盘余量。
- 给备份与恢复做演练。WAL 是恢复未 Flush 写入的机制,不是独立的备份策略。