强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

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

扩展阅读

  1. RocksDB WikiGitHub Wiki
  2. RocksDB 性能调优指南Tuning Guide
  3. LevelDB vs RocksDB 对比论文“Benchmarking LSM Key-Value Stores” (VLDB 2020)
  4. PebbleDB:CockroachDB 的 Go 实现 RocksDB 替代

第 13 章 · Docker 部署 | 第 15 章 · 生产最佳实践