LevelDB 完全指南 / 第 14 章 · LevelDB vs RocksDB
第 14 章 · LevelDB vs RocksDB
14.1 RocksDB 的诞生
RocksDB 是 Facebook 于 2013 年从 LevelDB 分支出来的一个项目。它的目标是在 LevelDB 的基础上,针对大规模生产环境进行优化,特别是 SSD 和多核场景。
时间线:
2011: Google 开源 LevelDB
2012: Facebook 在内部使用 LevelDB,发现性能瓶颈
2013: RocksDB 从 LevelDB 1.5 分支,开始独立发展
2014: RocksDB 3.0,引入 Column Family
2015: RocksDB 4.0,Universal Compaction
2018: RocksDB 5.0,BlobDB(Value 分离)
2021: RocksDB 6.0,Remote Compaction
2023: RocksDB 8.0,持续活跃开发
14.2 核心特性对比
存储与写入
| 特性 | LevelDB | RocksDB |
|---|
| 存储引擎 | LSM-Tree | LSM-Tree |
| 并发写入 | ❌ 单写者 | ✅ 多写者 |
| WriteBatch | ✅ | ✅ |
| Column Family | ❌ | ✅ |
| 原子写入 | ✅ 单批次 | ✅ 跨 CF 原子写入 |
Compaction
| 特性 | LevelDB | RocksDB |
|---|
| Compaction 策略 | Level-based | Level / Universal / FIFO |
| 后台线程数 | 1 | 可配置(多线程) |
| 手动 Compaction | ✅ CompactRange | ✅ 更多控制选项 |
| Remote Compaction | ❌ | ✅ |
| 动态调整 | ❌ | ✅ 动态调整 Compaction 参数 |
压缩
| 特性 | LevelDB | RocksDB |
|---|
| 压缩算法 | Snappy(默认) | Snappy / Zlib / LZ4 / ZSTD / 无 |
| 每层独立压缩 | ❌ | ✅ 不同层使用不同压缩 |
| 字典压缩 | ❌ | ✅ (ZSTD) |
| 压缩线程 | 同步 | 异步(可配置并行度) |
缓存与内存
| 特性 | LevelDB | RocksDB |
|---|
| Block Cache | LRU | LRU / Clock / 自定义 |
| Cache 分片 | ❌ | ✅ (ShardedCache) |
| 内存表 | SkipList | SkipList / HashSkipList / Vector / HashLinkList |
| 压缩表(前缀) | ❌ | ✅ Prefix Bloom |
备份与复制
| 特性 | LevelDB | RocksDB |
|---|
| 内置备份 | ❌ | ✅ (BackupEngine) |
| Checkpoint | ❌ | ✅ (硬链接快照) |
| Change Data Capture | ❌ | ✅ (WalFilter) |
| 跨列族 Snapshot | ❌ | ✅ |
14.3 性能对比
基准测试结果(NVMe SSD,100GB 数据集)
| 测试项 | LevelDB | RocksDB | 提升 |
|---|
| 顺序写入 | 150 MB/s | 350 MB/s | 2.3x |
| 随机写入 | 30 MB/s | 150 MB/s | 5x |
| 顺序读取 | 500 MB/s | 600 MB/s | 1.2x |
| 随机读取(有 Bloom) | 200K ops/s | 400K ops/s | 2x |
| 写放大 | 15-30x | 4-10x | 3x |
| 空间放大 | 1.1x | 1.05x | 更小 |
⚠️ 注意:以上数据为典型场景下的近似值,实际性能取决于硬件、数据特征和配置参数。
14.4 RocksDB 独有特性详解
特性一:Column Family(列族)
// LevelDB:只能用前缀区分不同类型的数据
db->Put(wopts, "user:1001:name", "张三");
db->Put(wopts, "config:max_retry", "3");
// RocksDB:不同 Column Family 独立管理
rocksdb::ColumnFamilyHandle* user_cf;
rocksdb::ColumnFamilyHandle* config_cf;
db->CreateColumnFamily(rocksdb::ColumnFamilyOptions(), "user", &user_cf);
db->CreateColumnFamily(rocksdb::ColumnFamilyOptions(), "config", &config_cf);
db->Put(wopts, user_cf, "1001:name", "张三");
db->Put(wopts, config_cf, "max_retry", "3");
// 不同 CF 可以有不同的 Compaction 策略、压缩方式等
特性二:Universal Compaction
// LevelDB:只有 Level-based Compaction
// RocksDB:可以选择更写入友好的 Universal Compaction
rocksdb::Options options;
options.compaction_style = rocksdb::kCompactionStyleUniversal;
// Universal Compaction 特点:
// - 更低的写放大
// - 适合写入密集型场景
// - 空间放大会稍微增大
特性三:BlobDB(Value 分离存储)
// 场景:Value 很大(>1KB),不希望 Compaction 频繁移动
rocksdb::Options options;
options.enable_blob_files = true;
options.min_blob_size = 1024; // Value > 1KB 时分离存储
options.blob_file_size = 256 * 1024 * 1024; // Blob 文件大小
// 大 Value 存储在独立的 Blob 文件中
// Compaction 只移动 Key + Blob 引用,减少 I/O
特性四:Rate Limiter
// 限制 Compaction 的 I/O 带宽,避免影响前台读写
rocksdb::RateLimiter* rate_limiter = rocksdb::NewGenericRateLimiter(
100 * 1024 * 1024, // 100 MB/s
100000, // refill period (microseconds)
10, // fairness
rocksdb::RateLimiter::Mode::kWritesOnly
);
options.rate_limiter = rate_limiter;
特性五:Prefix Seek / Prefix Bloom
// LevelDB:前缀扫描需要手动检查
for (it->Seek(prefix); it->Valid() && it->key().starts_with(prefix); it->Next()) { ... }
// RocksDB:原生前缀 Bloom Filter 支持
rocksdb::Options options;
options.prefix_extractor.reset(rocksdb::NewFixedPrefixTransform(8));
rocksdb::ReadOptions ropts;
ropts.prefix_same_as_start = true; // 只返回前缀匹配的结果
auto* it = db->NewIterator(ropts);
for (it->Seek(prefix); it->Valid(); it->Next()) { ... }
特性六:内置备份
// LevelDB:需要自己实现备份逻辑
// RocksDB:内置 BackupEngine
rocksdb::BackupEngine* backup_engine;
rocksdb::BackupEngine::Open(
rocksdb::Env::Default(),
rocksdb::BackupEngineOptions("/backup/path"),
&backup_engine
);
// 创建备份
backup_engine->CreateNewBackup(db);
// 恢复备份
backup_engine->RestoreDBFromBackup(1, "/data/leveldb", rocksdb::RestoreOptions());
// 列出所有备份
std::vector<rocksdb::BackupInfo> backup_info;
backup_engine->GetBackupInfo(&backup_info);
14.5 迁移指南
API 对比
| 操作 | LevelDB API | RocksDB API |
|---|
| 打开 | leveldb::DB::Open() | rocksdb::DB::Open() |
| 写入 | db->Put() | db->Put() |
| 读取 | db->Get() | db->Get() |
| 删除 | db->Delete() | db->Delete() |
| 迭代器 | db->NewIterator() | db->NewIterator() |
| 批量写入 | WriteBatch | WriteBatch |
| 快照 | GetSnapshot() | GetSnapshot() |
| 头文件 | leveldb/db.h | rocksdb/db.h |
迁移步骤
步骤 1: 替换头文件
#include "leveldb/db.h" → #include "rocksdb/db.h"
步骤 2: 替换命名空间
leveldb::DB* → rocksdb::DB*
leveldb::Options → rocksdb::Options
leveldb::Status → rocksdb::Status
步骤 3: 替换库文件
-lleveldb → -lrocksdb
步骤 4: 数据格式兼容
LevelDB 的 SSTable 格式和 RocksDB 不直接兼容
需要重新导入数据
步骤 5: 测试
运行完整测试套件
CMake 迁移
# LevelDB
find_package(leveldb REQUIRED)
target_link_libraries(app leveldb::leveldb)
# RocksDB
find_package(RocksDB REQUIRED)
target_link_libraries(app RocksDB::rocksdb)
14.6 选型决策树
需要嵌入式 KV 存储吗?
├── 否 → 使用 etcd / TiKV / Redis
└── 是 → 数据量多大?
├── < 1GB
│ └── 读写性能要求?
│ ├── 普通 → LevelDB ✅
│ └── 高性能 → LevelDB(简单够用)
├── 1GB - 100GB
│ └── 并发写入?
│ ├── 单线程写 → LevelDB ✅
│ └── 多线程写 → RocksDB ✅
└── > 100GB
└── RocksDB ✅(更好的 Compaction、压缩、缓存)
选型建议
| 场景 | 推荐 | 原因 |
|---|
| 小型嵌入式应用 | LevelDB | 简单、依赖少、久经考验 |
| 区块链节点 | LevelDB / RocksDB | LevelDB 足够(Bitcoin/Ethereum) |
| 分布式数据库底层 | RocksDB | 多线程写、Column Family、更好的 Compaction |
| 时序数据库 | RocksDB | Universal Compaction、BlobDB |
| 配置存储 | LevelDB | 简单可靠 |
| 日志/消息队列 | LevelDB | 顺序写入简单高效 |
| 高吞吐写入 | RocksDB | 多写者、Rate Limiter |
| 云原生部署 | RocksDB | Checkpoint 备份、远程 Compaction |
14.7 常见误区
误区一:“RocksDB 是 LevelDB 的超集,所以一定用 RocksDB”
事实:RocksDB 更复杂,配置选项更多,调优更难。
- LevelDB 的简单性是优势
- 对于小数据集、单线程场景,LevelDB 性能足够
- 过度配置 RocksDB 可能导致意想不到的问题
误区二:“LevelDB 已经不再维护”
事实:LevelDB 仍在维护(最后更新 2021 年),只是更新不频繁。
- Google 内部仍在使用
- Chromium、Bitcoin 等项目依赖 LevelDB
- 代码稳定是优势
误区三:“可以直接从 LevelDB 迁移到 RocksDB”
事实:SSTable 格式不兼容,不能直接复制数据文件。
迁移方式:
1. 导出数据 → 导入新数据库
2. 从 WAL 日志重建
3. 使用应用层复制
14.8 本章小结
| 维度 | LevelDB | RocksDB |
|---|
| 定位 | 简洁的嵌入式 KV 存储 | 高性能生产级 KV 存储 |
| 并发写 | ❌ | ✅ |
| Compaction | Level-based | Level/Universal/FIFO |
| 压缩 | Snappy | Snappy/Zlib/LZ4/ZSTD |
| 备份 | 自行实现 | 内置 BackupEngine |
| 学习曲线 | 低 | 中等 |
| 代码复杂度 | ~3万行 | ~20万行 |
| 活跃度 | 中等 | 非常活跃 |
| 许可证 | BSD 3-Clause | Apache 2.0 |
扩展阅读
- RocksDB Wiki:GitHub Wiki
- RocksDB 性能调优指南:Tuning Guide
- LevelDB vs RocksDB 对比论文:“Benchmarking LSM Key-Value Stores” (VLDB 2020)
- PebbleDB:CockroachDB 的 Go 实现 RocksDB 替代
← 第 13 章 · Docker 部署 | 第 15 章 · 生产最佳实践 →