这是我参与「第四届青训营 」笔记创作活动的第 16 天!
关于 LSMT&存储引擎
LSMT
- 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 等。
- LSMT 通过 Append-only Write + 择机 Compact 来维护结构的索引树
存储引擎
- 单机数据库,如 MySQL 可分为:
- 计算层:主要负责 SQL 解析、查询优化,计划执行等。
- 存储层(存储引擎层):数据库著名的 ACID 特性,在 MySQL 中全部强依赖于存储引擎。
- ACID
- Atomicity
- Write-Ahead Log(WAL)/Redo Log
- Consistency(Correctness)
- 依赖于数据库整体
- Isolation
- Snapshot / 2PL(Phase Lock)
- Durability
- Flusher 遵循 Sync 语意
- Atomicity
- 存储引擎还负责:
- 屏蔽 IO 细节提供的更好的抽象
- 提供统计信息与 Predicate Push Down 能力
- 存储引擎不掌控 IO 细节,让操作系统接管,例如使用 mmap,会出现以下问题:
- 罗盘时机不确定造成的事务不安全
- IO stall
- 错误处理繁琐
- 无法完全发挥硬件性能
LSMT 存储引擎模型理论分析
Cloud-Native LSMT Storage Engine - HBase
- RocksDB 是单机存储引擎,但是 HBase 比 RocksDB 更“云(原生)”一些,SST 直接存储在 HDFS 上。
- 二者在理论存储模型上都是 LSMT
LSMT 模型算法复杂度分析
- T:size ratio,每层 LSMT 比上一层大多少,L0 大小为 1,则 L1 大小为 T,L2 为 T^2,以此类推
- L:level num,LSMT 层数 B:每个最小的 IO 单位能装载多少条记录
- M:每个 BloomFilter 有多少 bits
- N:每个 BloomFilter 生成时用了多少条 Key
- S:区间查询的记录数量
LSMT 模型算法复杂度分析 - Level
- Write
- 每条记录抵达最底层需要经过 L 次 Compact,每次 Compact Ln 的一个小 SST 和 Ln+1 的以一个大 SST。
- 设小 SST 的大小为 1,那么大 SST 的大小则为 T,合并开销为 1+T,换言之将 1 单位 的 Ln 的 SST 推到 Ln+1 要耗费 1+T 的 IO,单次 Compact 写放大为 T。
- 每条记录得写入成本为 1/B 次最小单位 IO。
- O(Write_Level) = L * T * 1/B = T * L/B
- Point Lookup
- 对于每条 Key,最多有 L 个重叠的区间
- 每个区间都有 BloomFilter,失效率为 e^(-M/N),当只有 BloomFilter 失效时才会访问下一层。
- O(PointLookup_Level) = L * e^(-M/N)
LSMT 模型算法复杂度分析 - Tier
- Write
m - 设 SST 大小为 1,那么 T 个 SST Compact 的合并开销是 T,换言之将 T 单位的 Ln 的 SST 推到 Ln+1 要耗费 T 的 IO,次 Compact 的写放大为 T/T = 1.
- 每条记录的写入成本为 1/B 次最小单位 IO。 - O(Write_Tier) = L * 1 * 1/B = L/B
- Point Lookup
- 对于每条 Key,有 L 层。
- 每层最多有 T 个重叠区间的 SST,对于整个 SST 来说有 T * L 个可能命中的 SST,乘上 BloomFilter 的失效率,e^(-M/N),可得结果
- O(PointLookup_Tier) = L * T * e^(-M/N) = T * L * e^(-M/M)
总结
- Tier 策略降低了写放大,增加了读放大和空间放大
- Level 策略增加了写放大,降低了读放大和空间放大