这是我参与「第四届青训营 」 笔记创作活动的第11天
起源:BTree是1970年提出的,LSMT是1996年提出的。所以早起数据库都是B+Tree索引,新的数据库都是LSMT存储引擎,如 TiDB,CockroachDB,HBase,Canssandra,RocksDB 等
工作原理:通过Append-only Write + 择机Compact来维护结构的索引树
LSMT 存储引擎
存储引擎是什么?
传统数据库大致可以分为
-
计算层:负责SQL解析、查询优化、计划执行
-
存储层(存储引擎层):
- 数据库著名的ACID特性,在单机中都强依赖于存储引擎
- 屏蔽 IO 细节提供更好的抽象
- 提供统计信息与 Predicate Push Down 能力
子结构
-
SSTable:全称是Stored String Table,本质上就是一个KV结构的顺序排列的文件。如下图:
- SSTable是不可修改的,只会用新的SSTable来覆盖旧的
-
MemTable:存放在内存中的数据结构,可以快速实现增删改查,比如红黑树,Skiplist都行
-
log文件,记录数据发生的变化,用于服务器宕机时找回数据
整体架构
LSMT 与 B+Tree 的异同
- B+树,数据的插入是原地更新的,在发生不平衡或者节点容量到达阈值后,必须立即进行分裂来平衡
- 工程实践上用LSMT表示一个Append-only 和Lazy Compact的索引树,B+ Tree表示一个Inplace-Update和Instance Compact的索引树
- LSMT 与 B+Tree 可以用统一模型描述并且相互转化
LSMT 存储引擎的优势
- 顺序写模型对于 SSD 设备更友好
- SST 不可修改的特性使得其能使用更加紧凑的数据排列和加上压缩
- 后台延迟 Compact 能更好利用 CPU 多核处理能力,降低前台请求延迟
顺序与随机操作性能不对称,顺序写吞吐是随机性能的好几倍。顺序写是一个对设备很友好的操作,LSMT符合这一点,但是B+Tree依赖原地更新,导致随机写
- LSMT的存储引擎的顺序写特性更适合现代计算机体系结构
LSMT实现和优化
HBase实现
HBase中的SST 直接存储于 HDFS 上,Meta 信息 RocksDB 自己管理维护于 Manifest 文件,HBase 放置于 ZK。
RocksDB实现
-
批量WAL写入,多个writer选leader一次性写WAL
- 好处:可以批量聚合请求,避免频繁提交小 IO
- WAL不必须落盘,提交到kernel的页缓存就可。Kernel自身的聚合io再下刷能够降低了操作系统调度线程的开销。
-
并发MemTable更新,WAL一次性写入之后唤醒其他writer进行并行写入。最后一个完成的进行收尾工作
优化
-
superVersion:拥有MemTable/ImmemTable/ssT三部分数据并且提供快照功能的组件
- 为了让渡操作有更好的规模,进行Thread Local SuperVersion
- 有了Thread Local 缓存,读取只需要检查SuperVersion并标记缓存正在被使用即可,对cpu缓存友好
-
BloomFilter:加速查找,在SST中嵌入 BloomFilter
-
Compact:将Key区间有重叠或者无效数据较多的SST进行合并,一次来加速读取或者回收空间
-
Level:每一个层不允许有SST的key区间重合
- 增加了写放大,降低了读和空间放大。
-
Tier:每一个层允许有SST的key区间重合
- 策略:用读放大的增加换取了写放大的减小。
-
\