LSM引擎:项目说明
项目介绍
本项目主要实现一个LSM Tree引擎,并在其基础上实现以下内容:
- 对Redis RESP协议的兼容,
- 基于RESP协议的redis server封装
- ACID事务
- MVCC(多版本并发控制)
- WAL(Write-Ahead-Log)
- 崩溃恢复
学习该项目是为了提升代码能力,学习巩固数据库相关知识尤其是ACID,MVCC等,学习Redis中间件相关知识
LSM Tree简介
-
LSM Tree(Log Structured Merge Tree)是一种专为写密集型场景优化的磁盘数据结构,它把磁盘随机写替换为追加写,并在后台用合并的方式整理磁盘数据。
-
与B+树这类原地更新的数据结构不同,LSM Tree不会删除或更改旧数据,而是通过追加写的方式向内存和磁盘追加新数据覆盖旧数据。
-
相较于B+树这类传统磁盘数据结构,LSM Tree更适合用于写密集的,不需要删除的数据库,例如日志数据或者时序数据。
-
LSM Tree的主要组件有MemTable,Immutable MemTable,SSTable,WAL,Compaction其中:
- MemTable用于管理暂时写入内存中的数据,一般用跳表或平衡树管理,支持快速增删改查
- Immutable MemTable只读,等待系统刷盘
- SSTable(Sorted String Table)存储按照key有序排列的文件,是LSM Tree实际存放数据的组件
- WAL负责记录写操作,用于崩溃后恢复
- Compaction负责对SST文件进行合并,因为随着数据量增加,SST的文件数量增多,并且可能出现重复数据,这些会导致数据查询效率降低,Compaction会将合并后的数据推向更深层
-
LSM的写流程:
- 写入WAL持久化
- 写入MemTable
- MemTable静态化为Immutable MemTable
- 系统将Immutable MemTable刷盘到SST
-
LSM的读流程:
- 在MemTable查询数据
- 在Immutable MemTable按照时间倒序查找
- 在SST从L0开始按照时间倒序查找
-
优势
- 极高的写入吞吐:顺序写充分利用磁盘带宽(尤其是 SSD)
- 天然支持批量加载:适合时序数据、日志、监控等场景
- 崩溃恢复简单:依赖 WAL + 不可变文件,恢复逻辑清晰
- 易于压缩:SSTable 不可变,可以采用高效压缩算法
-
局限
- 读放大:最坏情况需查多层 SSTable
- 写放大:Compaction 会重写大量数据(尤其是 Leveled 策略)
- 空间放大:旧版本数据在 Compaction 前占用额外空间
- 性能抖动:后台 Compaction 可能与前台读写争用资源
项目环境和技术
- 在WSL Ubuntu环境下实现该项目
- 使用C++17实现
- 使用xmake和vcpkg管理包,使用xmake管理项目编译
- 使用gtest编写测试
架构图
flowchart TD
subgraph 协议层
C[Redis Client]
R[RESP Parser]
end
C --> R
R --> API[myLSM API<br/>Put / Get / Delete / Txn]
subgraph 内存层
M[MemTable<br/>SkipList 活跃写入]
I[Immutable MemTable<br/>等待刷盘]
W[WAL<br/>崩溃恢复]
end
API --> M
API -.-> W
M --> I
subgraph 磁盘层
direction TB
L0[L0 SSTable<br/>无序,键范围可重叠]
L1[L1 SSTable<br/>有序,键范围不重叠]
L2[L2 ~ Ln<br/>更大更旧,持续 Compaction]
end
I --> L0
L0 -->|Compaction| L1
L1 -->|Compaction| L2
subgraph 核心能力
MVCC[MVCC 多版本并发]
ACID[ACID 事务]
REC[崩溃恢复]
end
API -.-> MVCC
API -.-> ACID
W -.-> REC
浙公网安备 33010602011771号