强曰为道

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

第 1 章 · 简介与历史

第 1 章 · 简介与历史

1.1 LevelDB 是什么

LevelDB 是由 Google 开源的嵌入式键值存储引擎(Embedded Key-Value Store)。它不是一个独立运行的数据库服务,而是一个库——你可以将它链接到自己的应用程序中,直接在进程内完成数据的读写操作。

属性说明
开发者Google(Jeff Dean & Sanjay Ghemawat)
开源时间2011 年
语言C++
许可证BSD 3-Clause
存储模型LSM-Tree(Log-Structured Merge-Tree)
数据模型<Key, Value> 二元组,Key 和 Value 均为任意字节序列
排序方式Key 按字典序(bytewise comparator)排列
并发支持单写多读(one writer, multiple readers)

💡 提示:LevelDB 的设计灵感来自 Google 内部的 Bigtable 存储系统。如果你了解 Bigtable 的 SSTable 和 MemTable 概念,会发现 LevelDB 是这些思想的精简实现。


1.2 历史背景

诞生故事

2011 年,Google 的 Jeff Dean 和 Sanjay Ghemawat(MapReduce 论文的两位作者)将 LevelDB 开源。他们的目标是创建一个轻量级、高性能的嵌入式存储引擎,填补当时开源生态中 “进程内高性能 KV 存储” 的空白。

版本演进

时间版本里程碑
2011.05v1.0首次开源
2012v1.2改进 Compaction 策略
2013v1.5性能优化,修复并发 bug
2014v1.12RocksDB 从 Facebook 分支独立发展
2018v1.20CMake 构建支持
2021v1.23当前最新稳定版

分支与衍生项目

LevelDB 的成功催生了一系列衍生项目:

                    ┌──────────────┐
                    │   LevelDB    │ (Google, 2011)
                    └──────┬───────┘
            ┌──────────────┼──────────────┐
            ▼              ▼              ▼
    ┌──────────────┐ ┌──────────┐ ┌──────────────┐
    │   RocksDB    │ │ HyperDB  │ │ goleveldb    │
    │ (Facebook)   │ │ (学术)   │ │ (Go 实现)    │
    └──────────────┘ └──────────┘ └──────────────┘
            │
            ▼
    ┌──────────────┐
    │  PebblesDB   │
    │  (UT Austin) │
    └──────────────┘
衍生项目维护者语言特点
RocksDBFacebookC++最活跃分支,大量生产优化
goleveldbsyndtrGo纯 Go 实现,API 兼容
LevelDB (Java)GoogleJava官方 Java 移植
PlyvelwbolsterPythonCython 绑定
level-rocksdbLevelNode.jsNode.js 绑定

1.3 LSM-Tree 核心思想

LevelDB 的底层数据结构是 LSM-Tree(Log-Structured Merge-Tree),由 Patrick O’Neil 等人在 1996 年的论文中提出。

传统 B-Tree 的瓶颈

传统数据库(如 MySQL InnoDB)使用 B-Tree 存储数据。B-Tree 的随机写(Random Write)在磁盘上会导致大量寻道开销:

B-Tree 随机写:
  写入 Key=42 → 寻道到 Page #387 → 修改 → 写回
  写入 Key=17 → 寻道到 Page #125 → 修改 → 写回
  写入 Key=99 → 寻道到 Page #512 → 修改 → 写回
  (每次写入可能触发随机 I/O)

LSM-Tree 的解法:顺序写

LSM-Tree 的核心思想是将随机写转换为顺序写

  1. 写入时:先写入内存中的 MemTable(类似跳表),同时追加 WAL(Write-Ahead Log)保证持久性
  2. MemTable 满了:冻结为 Immutable MemTable,刷盘生成 SSTable 文件
  3. 后台 Compaction:定期合并多个 SSTable,清理过期数据
LSM-Tree 写入流程:

  写请求 ──→ [MemTable (内存)] ──→ 满了 ──→ [SSTable L0 (磁盘)]
                │                                      │
                ▼                                      ▼
           [WAL 日志]                          [Compaction]
                                                    │
                                              ┌─────┴─────┐
                                              ▼           ▼
                                         SSTable L1   SSTable L1
                                              │
                                              ▼
                                         SSTable L2

读写性能对比

操作B-TreeLSM-Tree
写入O(log n),随机 I/OO(1),顺序 I/O
点读O(log n),1-2 次 I/OO(log n),可能多层查找
范围扫描高效(数据连续)较好(同一层数据连续)
空间放大较低较高(存在冗余副本)
写放大较低较高(Compaction 导致)

⚠️ 注意:LSM-Tree 的经典权衡是写放大(Write Amplification)空间放大(Space Amplification)。Compaction 过程中,数据会被反复读写,这就是写放大的来源。


1.4 LevelDB 的特性概览

核心特性

特性说明
有序键值存储Key 按字典序排列,支持高效范围扫描
原子批量写入WriteBatch 保证一组操作的原子性
快照读Snapshot 提供时间点一致性视图
自定义比较器可自定义 Key 的排序规则
Bloom Filter减少无效磁盘读取
Snappy 压缩SSTable 数据块自动压缩
数据校验CRC32 校验保证数据完整性

不支持的特性

缺失特性说明替代方案
网络接口无客户端-服务端协议自行封装 RPC
权限控制无用户认证/授权应用层实现
事务(ACID)无跨 Key 事务支持WriteBatch(单批次原子)
多列族不支持 Column Family使用多个 DB 实例
增量备份无内置备份 API文件级复制 + Snapshot
压缩策略选择仅 Level-basedRocksDB 支持 Universal/FIFO

1.5 适用场景分析

✅ 推荐使用 LevelDB 的场景

场景一:区块链状态存储

以太坊(Go-Ethereum)和比特币都使用 LevelDB 存储区块链状态:

// 以太坊风格的区块头存储
db->Put(WriteOptions(), "block:1000:hash", block_hash);
db->Put(WriteOptions(), "block:1000:header", serialized_header);
db->Put(WriteOptions(), "state:account:0xABC...", account_state);

为什么适合:写多读少、数据有序、嵌入式无需额外服务。

场景二:时序数据缓存层

IoT 设备 → 采集数据 → LevelDB(本地缓存)→ 批量上传 → 云端时序数据库

为什么适合:高吞吐写入、本地持久化防丢失、顺序 Key 天然支持时间排序。

场景三:搜索引擎倒排索引

// Key: "term:leveldb" + doc_id → Value: tf-idf 分数
std::string key = "term:leveldb" + "\x00" + std::to_string(doc_id);
db->Put(WriteOptions(), key, SerializeScore(tf_idf));

为什么适合:有序遍历支持前缀查询,批量写入构建索引高效。

场景四:配置中心/服务发现

// 服务注册
db->Put(WriteOptions(), "service:auth:node1", "192.168.1.10:8080");
db->Put(WriteOptions(), "service:auth:node2", "192.168.1.11:8080");

// 查询所有 auth 服务节点
auto iter = db->NewIterator(ReadOptions());
for (iter->Seek("service:auth:");
     iter->Valid() && iter->key().starts_with("service:auth:");
     iter->Next()) {
    // 遍历所有 auth 节点
}

❌ 不推荐使用 LevelDB 的场景

场景原因推荐替代
高并发写入(多线程写)仅支持单写者RocksDB
超大数据集(TB 级)Compaction 性能下降RocksDB / TiKV
需要 SQL 查询无关系型功能SQLite / PostgreSQL
分布式存储无内置复制/分片etcd / TiKV
强事务需求仅支持单批次原子SQLite / FoundationDB
频繁删除空间回收延迟RocksDB(支持 Tombstone 优化)

1.6 谁在使用 LevelDB

项目/公司使用方式
ChromiumIndexedDB 底层存储
Go-Ethereum区块链状态存储
Bitcoin Core区块索引(早期版本)
Apache Kafka内部状态存储(Kafka Streams)
TensorFlow模型 checkpoint 存储
华为鸿蒙分布式数据管理底层
ElasticSearch内部 Lucene 辅助存储

1.7 与同类技术对比

特性LevelDBSQLiteBerkeleyDBRocksDB
数据模型KV关系型KVKV
存储引擎LSM-TreeB-TreeB-Tree/HashLSM-Tree
嵌入式
事务批次原子完整 ACID完整 ACID批次原子
多线程写
语言C++CC/C++C++
许可证BSDPublic DomainAGPLApache 2.0
活跃度中等非常活跃非常活跃

1.8 本章小结

要点内容
定位嵌入式有序键值存储引擎
核心架构LSM-Tree,顺序写优先
优势写入高性能、简单可靠、久经考验
劣势单线程写、无网络层、Compaction 开销
适用写多读少、嵌入式、数据量适中

扩展阅读

  1. LSM-Tree 原始论文:O’Neil, P., et al. “The Log-Structured Merge-Tree (LSM-Tree)” (1996)
  2. Bigtable 论文:Chang, F., et al. “Bigtable: A Distributed Storage System for Structured Data” (2006)
  3. LevelDB 作者演讲:Jeff Dean - “Achieving Rapid Response Times in Large Online Services”
  4. RocksDB WikiTuning Guide
  5. Designing Data-Intensive Applications:Martin Kleppmann, Chapter 3 “Storage and Retrieval”

下一章第 2 章 · 编译安装与语言绑定