系列简介
本系列从磁盘的物理结构出发,逐层向上——文件系统、块层与 I/O 栈、B 树与 LSM 树、写路径与读路径、WAL 与崩溃恢复、缓冲池、压缩编码、MVCC、列式存储——再从单机延伸到分布式——RAID 与纠删码、分布式文件系统、对象存储、云原生存储,最终以手写一个迷你 LSM 存储引擎收尾。
核心理念:存储是所有数据系统的地基。理解存储,才能理解数据库、消息队列、对象存储等上层系统的性能边界与设计取舍。
系列定位
- 不是某个存储产品的使用手册——而是理解存储系统设计思维的方式
- 不是从零写一个生产级存储引擎——而是读懂生产级存储系统的设计决策
- 是从”会用存储”到”理解存储”的认知升级——知道为什么 SSD 写入会放大、为什么 LSM 树写快读慢、为什么云数据库要计算存储分离
场景驱动阅读路线
不想按部就班地从第 1 章读到第 19 章?没问题。以下 5 条路线从你日常遇到的真实问题出发,按”你需要什么→存储系统怎么实现”的顺序串联章节。每条路线可独立阅读,前置依赖已在路线内标注。
路线总览
路线A:我的写入为什么慢
场景:写入 QPS 上不去、SSD 寿命告警、Compaction 导致延迟毛刺、WAL 成为瓶颈——写入慢的根因在哪?
| 顺序 | 章节 | 为什么读这章 |
|---|---|---|
| 1 | Ch1 存储全景 | 建立存储层级与性能边界的全局认知 |
| 2 | Ch2 磁盘与 SSD | 核心:SSD 写入放大、擦除块、FTL 映射——物理层决定了写入天花板 |
| 3 | Ch6 LSM 树深入 | 核心:写入优化的数据结构——MemTable、SSTable、Compaction 策略 |
| 4 | Ch7 写路径 | 完整写路径:从请求到持久化——WAL、刷盘、Group Commit |
| 5 | Ch17 存储引擎对比 | InnoDB vs RocksDB vs TiKV——不同引擎的写入取舍 |
路线逻辑:先理解物理层的写入限制(Ch2),再理解 LSM 树如何优化写入(Ch6),然后走完整个写路径(Ch7),最后对比不同引擎的写入策略(Ch17)。
路线B:我的读取为什么慢
场景:点查延迟高、范围扫描慢、缓存命中率低、Bloom Filter 没起作用——读取慢的根因在哪?
| 顺序 | 章节 | 为什么读这章 |
|---|---|---|
| 1 | Ch1 存储全景 | 理解存储层级对读取性能的影响 |
| 2 | Ch5 B 树深入 | 核心:B+ 树页面组织、分裂合并、Latch 机制——读优化的数据结构 |
| 3 | Ch8 读路径 | 完整读路径:从请求到数据——Bloom Filter、Block Cache、预取 |
| 4 | Ch10 缓冲池 | 核心:LRU 变体、脏页刷盘、双写缓冲——内存中的读取加速 |
| 5 | Ch11 压缩与编码 | 压缩如何减少 I/O——RLE、字典编码、Parquet 列存压缩 |
路线逻辑:先理解 B 树如何加速读取(Ch5),再走完整个读路径(Ch8),然后理解缓冲池如何减少磁盘访问(Ch10),最后看压缩如何进一步减少 I/O(Ch11)。
路线C:数据安全与可靠性
场景:磁盘故障、节点宕机、机房断电、数据损坏——如何保证数据不丢、服务不停?
| 顺序 | 章节 | 为什么读这章 |
|---|---|---|
| 1 | Ch1 存储全景 | 理解存储系统的可靠性层次 |
| 2 | Ch9 WAL 与崩溃恢复 | 核心:ARIES 算法、LSN、检查点——单机崩溃恢复的工业标准 |
| 3 | Ch14 RAID 与纠删码 | 多盘冗余——RAID 级别、Reed-Solomon 编码、故障域 |
| 4 | Ch15 分布式文件系统 | 分布式冗余——Ceph CRUSH、RADOS、副本放置策略 |
| 5 | Ch16 对象存储 | 超大规模冗余——MinIO/S3 纠删码、多地域复制 |
路线逻辑:从单机崩溃恢复(Ch9)到多盘冗余(Ch14),再到分布式冗余(Ch15),最终到超大规模的对象存储冗余(Ch16)。
路线D:存储系统怎么选
场景:OLTP 选 InnoDB 还是 RocksDB?分析场景选行存还是列存?云上选 EBS 还是对象存储?计算存储分离值不值得?
| 顺序 | 章节 | 为什么读这章 |
|---|---|---|
| 1 | Ch1 存储全景 | 建立存储分类体系的全局认知 |
| 2 | Ch17 存储引擎对比 | 核心:InnoDB/RocksDB/TiKV 对比、RUM 猜想——选型的理论框架 |
| 3 | Ch13 列式存储 | 分析场景的存储选择——Parquet/ORC、向量化执行 |
| 4 | Ch18 云原生存储 | 云上存储架构——Aurora/Neon 计算存储分离 |
| 5 | Ch16 对象存储 | 海量非结构化数据的存储选择——MinIO/S3 |
路线逻辑:先建立选型框架(Ch17),再理解分析场景的列存(Ch13),然后看云原生架构的存储变革(Ch18),最后了解对象存储的适用场景(Ch16)。
路线E:存储底层怎么实现的
场景:想深入理解存储系统的内部实现——磁盘怎么工作?文件系统怎么组织?B 树和 LSM 树怎么实现?如何手写一个存储引擎?
| 顺序 | 章节 | 为什么读这章 |
|---|---|---|
| 1 | Ch2 磁盘与 SSD | 物理基础:HDD 寻道、SSD 擦除块、FTL 映射 |
| 2 | Ch3 文件系统 | 数据组织:ext4/XFS/Btrfs、日志、CoW |
| 3 | Ch4 块层与 I/O 栈 | I/O 路径:blk-mq、IO 调度、多队列 |
| 4 | Ch5 B 树深入 | 读优化结构:页面组织、分裂合并、Latch |
| 5 | Ch6 LSM 树深入 | 写优化结构:MemTable、SSTable、Compaction |
| 6 | Ch19 综合实战 | 手写迷你 LSM 存储引擎——综合运用前 18 章知识 |
路线逻辑:从物理层(Ch2)到文件系统层(Ch3)到块层(Ch4),再到数据结构层(Ch5、Ch6),最终动手实现(Ch19)。
路线交叉参考
同一章节在不同路线中的关注点不同:
| 章节 | 路线A 关注点 | 路线B 关注点 | 路线C 关注点 | 路线D 关注点 | 路线E 关注点 |
|---|---|---|---|---|---|
| Ch1 | 存储层级与写入边界 | 存储层级与读取延迟 | 可靠性层次 | 存储分类体系 | — |
| Ch2 | SSD 写入放大 | — | — | — | 物理结构 |
| Ch3 | — | — | — | — | 文件组织 |
| Ch4 | — | — | — | — | I/O 路径 |
| Ch5 | — | B+ 树读取优化 | — | — | 页面操作 |
| Ch6 | LSM 写入优化 | — | — | — | SSTable/Compaction |
| Ch7 | 完整写路径 | — | — | — | — |
| Ch8 | — | 完整读路径 | — | — | — |
| Ch9 | — | — | ARIES 恢复 | — | — |
| Ch10 | — | 缓冲池与 LRU | — | — | — |
| Ch11 | — | 压缩减少 I/O | — | — | — |
| Ch12 | — | — | — | — | — |
| Ch13 | — | — | — | 列存选型 | — |
| Ch14 | — | — | RAID 纠删码 | — | — |
| Ch15 | — | — | Ceph 冗余 | — | — |
| Ch16 | — | — | 对象存储冗余 | S3 选型 | — |
| Ch17 | 引擎写入对比 | — | — | RUM 选型 | — |
| Ch18 | — | — | — | 云原生架构 | — |
| Ch19 | — | — | — | — | 手写引擎 |
知识导图
以下导图展示 19 章知识之间的网络关系。与线性目录不同,这里强调跨层级的连接——一个”写入慢”的问题可能同时涉及 SSD 物理特性、LSM 树设计、写路径实现三个层级;一个”数据安全”的问题可能从 WAL 延伸到纠删码再到分布式副本。
概念关系图
章节网络关系图
知识关联参考表
按五层模型组织:物理层(硬件特性)→ 系统层(操作系统抽象)→ 结构层(数据组织方式)→ 机制层(存储引擎机制)→ 分布式层(跨节点系统)。同一行的条目之间存在直接的知识依赖或概念映射。
| 应用问题 | 物理层 | 系统层 | 结构层 | 机制层 | 分布式层 |
|---|---|---|---|---|---|
| 写入慢 | SSD 写入放大 Ch2 | 块层调度 Ch4 | LSM 树 Ch6 | 写路径 Ch7 | 引擎对比 Ch17 |
| 读取慢 | HDD 寻道 Ch2 | 页缓存 Ch10 | B+ 树 Ch5 | 读路径 Ch8 | — |
| 数据安全 | 磁盘故障 Ch2 | 文件系统日志 Ch3 | — | WAL/ARIES Ch9 | RAID/纠删码 Ch14 |
| 存储选型 | — | — | 行存/列存 Ch13 | RUM 猜想 Ch17 | 云原生 Ch18 |
| 海量数据 | — | — | 压缩编码 Ch11 | MVCC Ch12 | 对象存储 Ch16 |
| 崩溃恢复 | — | — | — | ARIES Ch9 | Ceph RADOS Ch15 |
系列大纲
以下是按章节编号排列的完整目录。建议结合上方的场景驱动阅读路线和知识导图选择适合你的阅读顺序。
Part 1:物理与系统篇 — 存储的基础设施
Part 2:数据结构篇 — 数据在磁盘上的组织
Part 3:核心机制篇 — 存储引擎的关键机制
| 章节 | 标题 | 核心内容 |
|---|---|---|
| 9 | WAL 与崩溃恢复 | ARIES 算法、LSN、检查点、Redo/Undo、崩溃恢复流程 |
| 10 | 缓冲池 | LRU 变体(2Q/LIRS)、脏页刷盘、双写缓冲、预读、并发控制 |
| 11 | 压缩与编码 | RLE、字典编码、位打包、Parquet 编码、Snappy/ZSTD/LZ4 对比 |
| 12 | MVCC 与版本管理 | Undo Log MVCC、Append-Only MVCC、VACUUM、快照隔离、版本链 |
Part 4:分布式与演进篇 — 从单机到云原生
| 章节 | 标题 | 核心内容 |
|---|---|---|
| 13 | 列式存储 | Parquet/ORC 格式、行列混存、向量化执行、Zone Map、谓词下推 |
| 14 | RAID 与纠删码 | RAID 0/1/5/6/10、Reed-Solomon 编码、故障域、重建性能 |
| 15 | 分布式文件系统 | Ceph CRUSH/RADOS、Gluster、元数据管理、数据均衡 |
| 16 | 对象存储 | MinIO/S3 架构、纠删码、多地域复制、生命周期管理 |
| 17 | 存储引擎对比 | InnoDB/RocksDB/TiKV 对比、RUM 猜想、读写放大分析 |
| 18 | 云原生存储 | Aurora/Neon 计算存储分离、存算分离架构、日志即数据库 |
| 19 | 综合实战 | 手写迷你 LSM 存储引擎:WAL + MemTable + SSTable + Bloom Filter + Compaction |
实践环境搭建
Docker Compose 一键启动
# 创建 docker-compose.ymlcat > docker-compose.yml << 'EOF'version: "3.8"services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: testdb ports: - "3306:3306" volumes: - mysql_data:/var/lib/mysql command: > --innodb-buffer-pool-size=256M --innodb-log-file-size=64M --innodb-flush-method=O_DIRECT
postgres: image: postgres:16 environment: POSTGRES_PASSWORD: root POSTGRES_DB: testdb ports: - "5432:5432" volumes: - pg_data:/var/lib/postgresql/data command: > -c shared_buffers=256MB -c wal_level=replica -c max_wal_size=1GB
rocksdb: image: ubuntu:22.04 ports: - "8080:8080" volumes: - rocksdb_data:/data - ./scripts:/scripts command: /bin/bash -c "apt-get update && apt-get install -y libgflags-dev libsnappy-dev zlib1g-dev libbz2-dev liblz4-dev libzstd-dev git build-essential && git clone https://github.com/facebook/rocksdb.git /rocksdb && cd /rocksdb && make static_lib -j$(nproc) && make install && sleep infinity"
minio: image: minio/minio:latest environment: MINIO_ROOT_USER: minioadmin MINIO_ROOT_PASSWORD: minioadmin ports: - "9000:9000" - "9001:9001" volumes: - minio_data:/data command: server /data --console-address ":9001"
volumes: mysql_data: pg_data: rocksdb_data: minio_data:EOF
# 启动所有服务docker compose up -d
# 验证连接docker compose exec mysql mysql -uroot -proot -e "SHOW ENGINE INNODB STATUS\G" | head -20docker compose exec postgres psql -U postgres -c "SELECT * FROM pg_stat_wal;"docker compose exec minio mc alias set local http://localhost:9000 minioadmin minioadmin示例数据初始化
-- MySQL: 创建测试表并观察存储行为CREATE TABLE storage_test ( id BIGINT PRIMARY KEY AUTO_INCREMENT, data VARCHAR(255), payload BLOB, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX idx_created (created_at)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED;
-- 插入测试数据INSERT INTO storage_test (data, payload)SELECT CONCAT('record_', n), REPEAT('x', 1000)FROM ( WITH RECURSIVE nums AS ( SELECT 1 AS n UNION ALL SELECT n + 1 FROM nums WHERE n < 100000 ) SELECT n FROM nums) t;
-- 观察 InnoDB 页面结构SELECT table_name, table_rows, data_length, index_length, data_freeFROM information_schema.tablesWHERE table_schema = 'testdb';-- PostgreSQL: 创建测试表并观察存储行为CREATE TABLE storage_test ( id BIGSERIAL PRIMARY KEY, data VARCHAR(255), payload BYTEA, created_at TIMESTAMP DEFAULT NOW());
-- 插入测试数据INSERT INTO storage_test (data, payload)SELECT 'record_' || n, decode(repeat('78', 1000), 'hex')FROM generate_series(1, 100000) AS n;
-- 观察页面信息SELECT relname, relpages, reltuples, pg_size_pretty(pg_relation_size(oid)) AS sizeFROM pg_classWHERE relname = 'storage_test';RocksDB 基准测试
# 编译 RocksDB 后运行基准测试cd /rocksdb
# 写入基准测试./db_bench --benchmarks=fillseq --num=1000000 --value_size=1024 --threads=1
# 读取基准测试./db_bench --benchmarks=readrandom --num=1000000 --value_size=1024 --threads=4
# Compaction 统计./db_bench --benchmarks=fillrandom --num=1000000 --stats_interval=10000 \ --stats_per_interval=1 --compaction_style=1MinIO 对象存储操作
# 安装 mc 客户端docker compose exec minio sh -c " mc alias set local http://localhost:9000 minioadmin minioadmin
# 创建桶 mc mb local/test-bucket
# 上传文件 mc cp /data/test-file local/test-bucket/
# 查看桶信息 mc ls local/test-bucket/
# 查看纠删码信息 mc admin info local"本系列的方法论
本系列遵循 物理 → 抽象 → 结构 → 机制 → 系统 的学习路径:
- 物理:从磁盘和 SSD 的物理特性出发——理解硬件的约束与边界
- 抽象:看操作系统如何抽象物理设备——文件系统、块层、I/O 栈
- 结构:理解数据在磁盘上的组织方式——B 树、LSM 树、列式存储
- 机制:深入存储引擎的核心机制——写路径、读路径、WAL、缓冲池、MVCC
- 系统:从单机扩展到分布式——RAID、分布式文件系统、对象存储、云原生存储
每章都遵循这一方法论,让你不仅知道”是什么”,更理解”为什么这样设计”。
推荐参考资料
经典教材与论文
| 资料 | 作者 | 特点 |
|---|---|---|
| 《Database Internals》 | Alex Petrov | 本系列核心参考,深入存储引擎与分布式系统实现 |
| ARIES 论文 | C. Mohan 等 | WAL 与崩溃恢复的工业标准算法,数据库恢复的奠基之作 |
| LSM-Tree 论文 | Patrick O’Neil 等 | LSM 树的原始论文,写入优化数据结构的理论基础 |
| 《Designing Data-Intensive Applications》 | Martin Kleppmann | 数据密集型应用设计的全景指南 |
| 《操作系统导论》(OSTEP) | Remzi Arpaci-Dusseau | 文件系统与存储的操作系统视角 |
| 《存储技术原理分析》 | 敖建旺 | 中文存储技术参考,覆盖磁盘到分布式 |
在线课程与资源
- CMU 15-445/645 — 数据库系统(Andy Pavlo 教授,存储引擎部分强烈推荐)
- MIT 6.824 — 分布式系统
- LWN.net — Linux 内核存储子系统最新进展
- Ceph 文档 — Ceph 分布式存储官方文档
官方文档
准备好开始了吗?从 存储全景 开始你的存储系统深入之旅吧!
参考
支持与分享
如果这篇文章对你有帮助,欢迎支持作者或分享给更多人
部分信息可能已经过时






