第 4 章 · 存储引擎与数据系统
“这一章学完,你能用 Go 写一个分布式搜索引擎——不是用 ES,是你自己写。“
本章覆盖的课程
| 编号 | 课程 | 本章的产出 |
|---|---|---|
| 037 | MySQL 实战45讲 | B+Tree 存储引擎 + WAL + MVCC + 事务 |
| 117 | Redis 核心技术与实战 | 内存数据结构 + 持久化 + 主从复制 |
为什么这一章最”值钱”
前 3 章是”内功”,这一章是”外功”——学完你手上就有了能变现的东西。
具体来说,学完这一章你会拥有:
- 一个 B+Tree 存储引擎:支持持久化、崩溃恢复、范围查询
- 一套 WAL + MVCC 实现:支持事务和并发读写
- 一个 LSM-Tree 引擎:写优化,适合时序和日志场景
- 一个倒排索引模块:全文检索的核心
- 一个分布式 KV 存储的骨架:分片 + 复制(第 5 章补上共识)
这五样东西,组合起来就是一个简化版的 Elasticsearch + Redis。
这就是你在开篇说的:“没有 ES 可以创建自己的 ES”。这一章就是兑现这句话的地方。
章节结构
| 文档 | 内容 | 动手项目 |
|---|---|---|
00-设计推演:从零造一个存储引擎.md | ★ 必读开篇:从内存 map 到 LSM / B+Tree 的八次失败与演进 | — |
01-B+Tree 存储引擎:从内存到磁盘.md | 页管理、B+Tree 落盘、Buffer Pool、Slotted Page | 磁盘版 B+Tree |
02-WAL、MVCC 与事务.md | 崩溃恢复、隔离级别、undo log、MVCC 实现 | WAL + MVCC 引擎 |
03-动手:从零构建分布式搜索引擎.md | LSM-Tree、倒排索引、分片、压缩 | 自己的 ES |
★ 阅读顺序提醒:先读
00-设计推演。它不讲”怎么做”,讲”为什么非得这么做”—— 从map[string]string出发,每前进一步都先遇到一个具体失败,再由失败逼出下一个设计。如果你只想从这一章拿走一样东西,拿走这一篇。实现会过时,推导链不会。
学完这一章,你应该能
- 解释为什么 B+Tree 的节点大小 = 磁盘页大小,并实现页管理
- 用 Go 实现一个磁盘版 B+Tree,支持持久化、分裂、范围查询
- 解释 WAL 的三种刷盘策略,以及它们对持久性和性能的影响
- 实现 MVCC:快照读、版本链、ReadView
- 解释 MySQL 的四个隔离级别各自怎么实现,以及各自的代价
- 用 Go 实现一个 LSM-Tree 引擎,含 MemTable、SSTable、Compaction
- 用 Go 实现一个倒排索引,支持全文检索和打分
- 设计一个分布式搜索引擎的分片策略
贯穿全章的核心问题
问题 1:持久化的本质是什么?
四个层次:
① 什么都没做
写内存就返回 → 断电数据丢失
② write() 系统调用
写到内核的 page cache → 断电还是丢(进程崩溃不丢)
③ fsync()
刷到磁盘 → 断电不丢(但磁盘可能有自己的缓存,需要 FUA)
④ 复制
写到多台机器 → 单机故障不丢
每一层都在用性能换持久性。 这一章你会看到 MySQL、Redis、RocksDB 各自选了哪一层,以及为什么。
问题 2:并发读写的本质是什么?
三种方案:
| 方案 | 思路 | 代价 |
|---|---|---|
| 锁 | 读加锁,写加锁,互斥 | 并发度低 |
| MVCC | 每个事务看到”快照”,读写不冲突 | 存储多版本,需要 GC |
| 串行化 | 所有操作排队 | 最简单,但吞吐低 |
MVCC 是现代数据库的标准答案。 它的核心洞察是:
“读”和”写”的冲突,可以通过”给每个读者一个快照”来消除。
代价是要存多个版本,并且要有机制回收旧版本。
问题 3:索引的本质是什么?
索引回答的是”怎么少读数据”。
无索引: 扫全表 → O(N) 次磁盘 IO
B+Tree: 树高 3-4 → O(log N) 次 IO(16 亿数据只要 3 次)
哈希: 1 次 IO,但不支持范围查询
布隆过滤器: 0 次 IO(如果确定不存在)
每一种索引结构,都是”查询能力”和”维护成本”的权衡。
一个重要的提醒
这一章的代码量是全书最大的。如果你只读不写,收获会非常有限。
建议的仓库结构:
~/gohard/ch04-storage/
├── btree/ B+Tree 存储引擎
├── wal/ WAL 实现
├── mvcc/ MVCC 引擎
├── lsm/ LSM-Tree 引擎
├── index/ 倒排索引
└── search/ 完整的分布式搜索引擎
每读完一节,把对应的代码跑起来,加几个 print 看看中间状态。
开始阅读:00-设计推演:从零造一个存储引擎