这是我参与【第四届青训营-大数据场】笔记创作活动的第14天
LSMT 是Log-Structured Merge-Tree 的缩写,由 Patrick O 'Neil etc.在 1996 年的论文 The Log-Structured Merge-Tree (LSM-Tree),提出。
相较而言,B-Tree 出现就早得多了,在 1970 年由 Bayer, R; McCreight, E.提出。
早期的数据库系统一般都采用 B-Tree 家族作为索引,例如 MySQL。2000 年后诞生的数据库大多采用 LSMT 索引,例如 Google BigTable,HBase,Canssandra等。
存储引擎是什么?
除了保障 ACID 以外,存储引擎还要负责:
- 屏蔽 IO 细节提供更好的抽象
- 提供统计信息与 Predicate Push Down能力
存储引擎不掌控 IO 细节,让操作系统接管,例如使用 mmap,会有如下问题:。落盘时机不确定造成的事务不安全. IO Stall
- 错误处理繁琐
- 无法完全发挥硬件性能
LSMT 与B+Tree 的异同
- LSMT 与 B+Tree 可以用统一模型描述
- 从高层次的数据结构角度来看,二者没有本质的不同,可以互相转化
- 工程实践上还是用 LSMT 来表示一个 Append-only 和 Lazy Compact 的索引树,B+Tree 来表示一个Inplace-Update 和 Instant Compact 的索引树。
- Append-only 和 Lazy Compact 这两个特性更符合现代计算机设备的特性。
为什么要采用 LSMT 模型?
All problems in computer science can be solved by another level of indirection Fro
-
在计算机存储乃至整个工程界都在利用 Indirection 处理资源的不对称性
-
存储引擎面对的资源不对称性在不同时期是不同的
-
RocksDB 是一款十分流行的开源 LSMT 存储引擎,最早来自 Facebook(Meta),应用于 MyRocks,TiDB 等数据库。
-
在字节内部也有 Abase,ByteKV,ByteNDB,Bytable 等用户。
-
因此接下来将会以 RocksDB 为例子介绍 LSMT 存储引擎的经典实现。
RocksDB
-
RocksDB 写入流程主要有两个优化,批量 WAL 写入(继承自 LevelDB)与并发 MemTable更新
-
RocksDB 在真正执行修改之前会先将变更写入 WAL,WAL写成功则写入成功。
Write
-
多个写入者会选出一个 Leader,由这个 Leader来一次性写入 WAL,避免小 IO。
-
不要求 WAL 强制落盘(Sync)时,批量提交亦有好处,Leader 可以同时唤醒其余 Writer,降低了系统线程调度开销。
LSMT 存储引擎的实现- Snapshot & SuperVision
-
RocksDB的数据由 3 部分组成,MemTable/ImmemTable /SST。持有这三部分数据并且提供快照功能的组件叫做 SuperVersion。
-
MemTable 和 SST 的释放依赖于引用计数。
-
对于读取来说,只要拿着 SuperVersion,从 MemTable一级一级向下,就能查到记录。
-
如果所有读者都给 SuperVersion 的计数加 1,读完后再减 1,那么这个原子引用计数器就会成为热点。CPU 在多核之间同步缓存是有开销的,核越多开销越大。
-
为了让读操作更好的 scale,RocksDB 做了一个优化是 Thread Local SuperVersion Cache
Get & BloomFilter
- RocksDB 的读取在大框架上和 B+ Tree 类似,就是层层向下。
- 相对于 B+Tree,LSMT 点查需要访问的数据块更多。为了加速点查,一般 LSMT 引擎都会在 SST 中嵌入 BloomFilter。
- [1,10] 表示这个索引块存储数据的区间在 1-10 之间。查询 2,就是顺着标绿色的块往下。