LSM 浅析「levelDB 基础机构」

785 阅读2分钟

这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战

  1. 就地更新 → B+Tree
  2. 非就地更新 → LSMTree

LSM 从设计上具有很好的顺序写的高性能特性,成为 写入密集 的数据库系统基础。

LSM问题

顺序写入的问题:

  1. 同一个 key 每次被操作的记录 <key, value, operation>,导致一个 key 占用多个存储空间
  2. 如何保证查询速度

如何解决这几个问题,成为 LSM 设计的精髓所在。

存储冗余

合并多个 key 的操作记录,只留下最后一个

新的问题:每次合并都需要遍历磁盘文件,类似与 STW ,会影响用户写入。

⇒ 那就将文件分段,多个文件做一个 key 的去重合并 → 多路归并算法

多路归并 ⇒ 就需要合并的多个组本身内部是排序好的 而且放在磁盘中进行 merge,IO 成本比较大 → 那就直接在内存中就排序好,落盘即可

⇒ 那么在内存中数据的组织形式 → skiplist

skiplist ⇒ 读取写入的复杂度均衡,主要是代码好写

总结一下:

  1. 合并文件数据
  2. 文件过大不利于合并 ⇒ 文件分段
  3. 多文件合并优化 ⇒ 多文件内部保证排序
  4. 用户插入时,内存中就排序好,然后再落盘
  5. 合并策略采取分层合并

查询优化

image.png

如何减少读放大:

  1. 通过不断地 major compaction 减少 sstable 的文件个数,尽可能在一层查询中找到想要的结果
  2. 快速判断过滤,判断一个 key 是否在某个 sstable 中

major compaction 上层的 sstable 在达到阈值之后,不断向下层 merge。类似多路归并

MemTable

  1. 保证插入有序,方便后续落盘之后的合并 ⇒ skiplist

  2. 频繁的内存分配比较耗费性能,尤其是这种小内存区域,容易产生内存碎片

    ⇒ 直接分配一个大内存,需要时改变指针引用就行;

    ⇒ 回收的实话直接将 memtable 的内存回收即可;

    memtable → Immutable 所以可以直接回收

  3. MemTable 会把 <key, value> 编码在一个 string,再将此 string 作为 key 插入

WAL

leveldb/log_format.md at master · google/leveldb

SSTable

image.png

Compaction

  1. MinorCompaction,immutable memtable持久化为 sst 文件
  2. Major Compaction,sst 文件之间的 compaction