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

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 核心特性对比

存储与写入

特性LevelDBRocksDB
存储引擎LSM-TreeLSM-Tree
并发写入❌ 单写者✅ 多写者
WriteBatch
Column Family
原子写入✅ 单批次✅ 跨 CF 原子写入

Compaction

特性LevelDBRocksDB
Compaction 策略Level-basedLevel / Universal / FIFO
后台线程数1可配置(多线程)
手动 Compaction✅ CompactRange✅ 更多控制选项
Remote Compaction
动态调整✅ 动态调整 Compaction 参数

压缩

特性LevelDBRocksDB
压缩算法Snappy(默认)Snappy / Zlib / LZ4 / ZSTD / 无
每层独立压缩✅ 不同层使用不同压缩
字典压缩✅ (ZSTD)
压缩线程同步异步(可配置并行度)

缓存与内存

特性LevelDBRocksDB
Block CacheLRULRU / Clock / 自定义
Cache 分片✅ (ShardedCache)
内存表SkipListSkipList / HashSkipList / Vector / HashLinkList
压缩表(前缀)✅ Prefix Bloom

备份与复制

特性LevelDBRocksDB
内置备份✅ (BackupEngine)
Checkpoint✅ (硬链接快照)
Change Data Capture✅ (WalFilter)
跨列族 Snapshot

14.3 性能对比

基准测试结果(NVMe SSD,100GB 数据集)

测试项LevelDBRocksDB提升
顺序写入150 MB/s350 MB/s2.3x
随机写入30 MB/s150 MB/s5x
顺序读取500 MB/s600 MB/s1.2x
随机读取(有 Bloom)200K ops/s400K ops/s2x
写放大15-30x4-10x3x
空间放大1.1x1.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 APIRocksDB API
打开leveldb::DB::Open()rocksdb::DB::Open()
写入db->Put()db->Put()
读取db->Get()db->Get()
删除db->Delete()db->Delete()
迭代器db->NewIterator()db->NewIterator()
批量写入WriteBatchWriteBatch
快照GetSnapshot()GetSnapshot()
头文件leveldb/db.hrocksdb/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 / RocksDBLevelDB 足够(Bitcoin/Ethereum)
分布式数据库底层RocksDB多线程写、Column Family、更好的 Compaction
时序数据库RocksDBUniversal Compaction、BlobDB
配置存储LevelDB简单可靠
日志/消息队列LevelDB顺序写入简单高效
高吞吐写入RocksDB多写者、Rate Limiter
云原生部署RocksDBCheckpoint 备份、远程 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 本章小结

维度LevelDBRocksDB
定位简洁的嵌入式 KV 存储高性能生产级 KV 存储
并发写
CompactionLevel-basedLevel/Universal/FIFO
压缩SnappySnappy/Zlib/LZ4/ZSTD
备份自行实现内置 BackupEngine
学习曲线中等
代码复杂度~3万行~20万行
活跃度中等非常活跃
许可证BSD 3-ClauseApache 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 章 · 生产最佳实践