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

LevelDB 完全指南 / 第 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.05 v1.0 首次开源
2012 v1.2 改进 Compaction 策略
2013 v1.5 性能优化,修复并发 bug
2014 v1.12 RocksDB 从 Facebook 分支独立发展
2018 v1.20 CMake 构建支持
2021 v1.23 当前最新稳定版

分支与衍生项目

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

                    ┌──────────────┐
                    │   LevelDB    │ (Google, 2011)
                    └──────┬───────┘
            ┌──────────────┼──────────────┐
            ▼              ▼              ▼
    ┌──────────────┐ ┌──────────┐ ┌──────────────┐
    │   RocksDB    │ │ HyperDB  │ │ goleveldb    │
    │ (Facebook)   │ │ (学术)   │ │ (Go 实现)    │
    └──────────────┘ └──────────┘ └──────────────┘
            │
            ▼
    ┌──────────────┐
    │  PebblesDB   │
    │  (UT Austin) │
    └──────────────┘
衍生项目 维护者 语言 特点
RocksDB Facebook C++ 最活跃分支,大量生产优化
goleveldb syndtr Go 纯 Go 实现,API 兼容
LevelDB (Java) Google Java 官方 Java 移植
Plyvel wbolster Python Cython 绑定
level-rocksdb Level Node.js Node.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-Tree LSM-Tree
写入 O(log n),随机 I/O O(1),顺序 I/O
点读 O(log n),1-2 次 I/O O(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-based RocksDB 支持 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

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

1.7 与同类技术对比

特性 LevelDB SQLite BerkeleyDB RocksDB
数据模型 KV 关系型 KV KV
存储引擎 LSM-Tree B-Tree B-Tree/Hash LSM-Tree
嵌入式
事务 批次原子 完整 ACID 完整 ACID 批次原子
多线程写
语言 C++ C C/C++ C++
许可证 BSD Public Domain AGPL Apache 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 章 · 编译安装与语言绑定