LSM Tree 简笔

LSM Tree

总览

image-20240310212524128

写流程:

image-20240310212629760

  • 就地写,写入memTable
  • 当active memTable 满后,转变为readOnly memTable, 在合适时机flush入磁盘。
  • 当前level数据满后,进行归并操作,把数据排序,去重后转入下一level。

背景介绍

两种场景,读多写少,写多读少。

原地写

写操作:找到老数据所在位置,更新, IO操作,慢。

读操作:空间利用率高。

追加写

写操作:直接追加。

读操作:日志末尾逆序检索,性能不稳定。

LSM Tree适用于写多读少,以写效率为首要目标,保持读效率在容忍范围内。

追加写存在的问题:

  • 空间浪费

    存在多份数据。

  • 读性能低

如何解决空间浪费:

异步运行一个日志压缩线程。对于同一个数据的内容进行合并,保留最新数据。

新的问题:并发的资源竞争问题。

拆分文件解决资源竞争

把本来一个追加写的大文件拆分成一个个小的Table,这样的话,读取操作只需要在较新的Table中进行,旧的Table可以另外异步compact。

image-20231213213024751

如何提高查找性能

在每个表中使得数据有序,引入二分,使得单个表中的查询变成logN级别。

image-20231213213640693

但是这样需要随机存储。与我们追加写的初衷相违背。

在DiskTable的基础上引入memTable(内存表),额外在内存中维护 memTable结构。

  • memTable在内存中缓存
  • memTable本身有序
  • 在memTable的写操作统一采用就地写
  • memTable是用户写操作的唯一入口
  • memTable达到一定数据量后写入磁盘,成为追加DiskTable

为什么引入memTable不会违背我们追加写的初衷,不会违背我们以写效率为目标的初衷呢?

内存随机存储的速度是磁盘随机存储的几百到几千倍

而我们的DiskTable依旧是追加写的形式。

image-20231213215545117

三个新的问题

memTable的数据易失

WAL(write-ahead-log) 预写日志: 在将数据写入memTable前,先将操作写入位于磁盘的log中,保证了可以通过重放WAL来恢复memTable。

为什么日志同样是往磁盘中写入,却不会影响性能?

WAL日志是追加写,磁盘顺序IO,并不会对性能造成过大影响。

image-20231213220302717

memTable写磁盘堵塞

将memTable分为两部分,Active memTable 和 ReadOnly memTable,当一个Active memTable 数据满时,转变为ReadOnly memTable,新的写入会使用新的Active memTable,ReadOnly memTable会进行磁盘持久化。

image-20231213220759977

memTable内部采用什么数据结构

跳表?红黑树?其实都行。

跳表(Skip List):

  • 优势:
    • 有更细的锁粒度,插入时涉及的节点较少。
    • 跳表是一种有序的数据结构,对范围查询有较好的支持。
    • 插入和删除的平均时间复杂度为O(log n)。
    • 实现相对简单,易于理解和调试。
  • 劣势:
    • 跳表的实现相对于红黑树来说,可能会占用更多的空间。
    • 需要维护多个层级,可能增加一些额外的开销。

红黑树(Red-Black Tree):

  • 优势:
    • 在插入和删除等操作方面,红黑树的常数因子较小,可能在某些情况下更快。
    • 红黑树的空间利用率较高,不需要额外的指针。
  • 劣势:
    • 实现相对复杂,难以理解和维护。
    • 对于范围查询,可能性能不如跳表。

有关DiskTable

  • DiskTable内部不存在重复kv数据对,内存就地写。

  • DiskTable内部kv数据对有序,调表/红黑树插入。

  • 每个memTable的视野有限,Table是一个相对较小的单位,解决单个Table的数据冗余并不能解决全局的数据冗余。

如何解决diskTable视野有限的情况?

Table 分层

  • 将磁盘中的文件分为level 0 ~ level k, 一共k + 1 层。
  • 每层的diskTable数量保持一致。
  • level i + 1 的容量是level i 的 T 倍,T 一般取10。
  • 每一层的数据容量满时,会向下层进行归并操作,排序并且去重。

image-20231214090527502

在LSM Tree 中, 在磁盘的存储中,diskTable用特定的数据结构 SSTable(Sorted String Tables) 存储。

  • 因为每一层的diskTable容量是上一层的数倍,在靠下的层次中,diskTable会很大,当我们对其进行读取的时候会显得很笨重。

SSTable做的优化:

  • 数据通常按照某种方式进行分块,使得查询时可以只加载所需范围的块,而不是整个 SSTable。这降低了查询时所需的 I/O 操作,提高了查询效率。
  • 每个SST会维护一组索引信息,记录了每个块的k_min 和 k_max

bloom filter

image-20231214093411199

posted on 2024-04-26 10:38  hanzug  阅读(6)  评论(0编辑  收藏  举报