论文阅读: Constructing and Analyzing the LSM Compaction Design Space(一)

566 阅读11分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天,点击查看活动详情

这篇论文是我花了最长时间阅读的论文之一,因为作者行文抛出的观点非常非常多,看的头晕,我反复对照并将所有图示重新编辑和总结

论文阅读: Constructing and Analyzing the LSM Compaction Design Space(一)

LSM-基本原理。 为了支持快速的数据ingestion,LSM-树在将插入、更新和删除(也就是一般的ingestion)的请求buffer在主内存中。一旦内存缓冲区变满,在缓冲区中按Key进行排序的entries被作为一个sorted run flush到树的磁盘组件中。

在实践中,一个sorted run是一个或多个不可变的文件的集合,这些文件通常具有相同的大小。对于一个有L层的LSM树,我们假设其第一层(第0层)是内存中的缓冲区,其余各层(第1层到第L-1层)是磁盘驻留的。在磁盘上,每个第i层(i>1)的容量比第i-1层的容量大T倍,其中T是树的大小比例。

事实上RocksDB、levelDB L0层也不是内存层呢。

LSM树中的压缩。 LSM树中的compaction是定期进行的­ ,以减少读取和空间放大,同时确保数据的一致性和查询的正确性。compaction是在一个或多个层次之间合并两个或更多的sorted run,以确保LSM树容量以指数级增长的大小保持层次。compaction通常在一个层次达到其容量时被调用,此时,compaction程序将数据从饱和的层次移动到下一个层次,该层次具有指数级的更大容量。在compaction过程中,任何重复的条目(由更新产生)和无效的条目(由删除产生)都会被删除,只保留­ ,即逻辑上正确的(最新的有效)版本。Com­pactions决定了磁盘驻留数据被重新组织的方式和时间,从而影响磁盘上的物理数据布局。

image-20221207133456192

我们在选择compaction策略时,面临诸多挑战,不知道怎么选。如果你在使用rocksdb,提供的compaction选项并不多,可能会觉得compaction无关紧要,事实上,诸如Cassandra,kudu等LSM base存储系统,提供了很多的compaction策略以应对不同workload,我们希望至少站在更高层次去看LSM存储引擎的compaction策略和可能的设计、调优空间。而这篇论文就起到了很好的扩宽视野作用。

背景知识

image-20221207194228605

图1:(a)最先进的LSM引擎所采用的不同compaction策略导致了引擎所提供的不同性能­ ;(b)LSM压实在设计基元方面的分类法。

这个图画的不错,作者认为RocksDB最差,可能是因为大家都参考其做个方面的调优吧

Cassandra精心设计了compaction策略等诸多原因,写是最强的

X-Engine的删除性能比较强,其他都较弱? 感觉过于主观,作者你写论文的时候,X-Engine都还没开源。实际上X-Engine有诸多的优化,blockcache回填避免compaction失效,对性能影响比较大的 Compaction 过程做了大量优化:所以,应该写性能有所提升?

  • 拆分数据存储粒度,利用数据更新热点较为集中的特征,尽可能的在合并过程中复用数据。
  • 精细化控制 LSM 的形状,减少 I/O 和计算代价,有效缓解了合并过程中的空间增大。

Lethe确实是为delete而生的LSM优化

image-20221207195252017

LSM-压缩:为了限制磁盘上sorted run的数量(从而促进快速查找和更好地利用空间),LSM树定期将i 层的runs(或部分runs)与i+1层的重叠运行进行排序合并。这个重新组织数据并在磁盘上创建更少的长sorted run的过程被称为压缩。然而,sort-merging数据的过程要求数据在磁盘和数据库内存之间来回移动。这导致了写入放大,在最先进的基于LSM的数据存储中可高达40倍。

局部压缩。 为了摊薄数据移动,从而避免延迟峰值,最先进的LSM引擎将数据组织成更小的文件,并以文件而不是level层级的粒度进行压缩。如果i层的增长超过了阈值,就会触发一个com­paction,从i层中选择一个文件(或一个文件子集)与i+1层中有重叠的key范围的文件进行压缩。这个过程被称为partial compaction。上图展示了LSM树中完全compaction和部分compaction程序的比较图。(a)当调用时,经典的full compaction,一次compaction整个level,而(b)部分compaction­ 以文件的粒度进行compaction。

compaction设计空间

论文作者提出了关于构建compaction设计空间的四个原语,我们确定了提供任意compaction策略结构化分解的设计原语。这使我们能够创建LSM压缩策略的分类法,包括所有经典的以及新的策略。

(i)触发器(即何时compaction)

(ii)数据布局(即compaction后如何组织数据)

(iii)粒度(即每次压缩多少数据)

(iv)数据移动策略(即,要压缩哪些数据)

image-20221207174420156

触发器trigger

image-20221207211728171

compaction触发器

compaction触发器是指可以启动compaction工作的一组事件。最常见的compaction触发器是基于LSM树中某个级别的饱和度。层级的饱和度i (1 ≤ iL - 1)通常被测量为存储在第i级的数据字节数与第i级的理论容量的比率。

这是常见的触发测量,我们希望LSM树是一个正常的树形结构,而不是倒三角。

一旦饱和度超过预定的阈值,第i层的一个或多个不可变的文件将被标记为压缩。一些LSM引擎使用一个级别中的文件数来计算饱和度。请注意,基于文件数的饱和度只有在所有不可变的文件都是同等大小的情况下才有效,或者对于有可调整的文件大小的系统。如果一个级别中的sorted runs的数量超过了预定义的阈值,无论一个级别的大小如何,都会触发 sorted runs compaction触发器来进行compaction。

其他compaction触发器包括文件的滞后性基于墓碑的生存时间空间读取放大。例如,为了确保更新和删除传播到树的更深层次,一些LSM引擎在创建期间为每个文件分配了一个生存时间(TTL)。每个文件可以在一个层次中生存一定的时间,一旦TTL过期,该文件就会被标记为compaction[30]。

RocksDB支持配置compaction的ttl触发器,而且支持TTL执行SSTable级别的compaction

另一个删除驱动的compaction触发器通过a different timestamp-based scheme(不知怎么翻译,这里说的又是Lethe LSM存储引擎) 的方案,确保LSM中的删除持久化有上界的延迟,每个包含至少一个墓碑的文件在每一层都被分配了一个特殊的TTL,在这个TTL到期时,文件被标记为需要compaction[51]。下面,我们介绍一个最常见的压缩触发器的列表。

  • i) Level saturation: level size goes beyond a nominal threshold
  • ii) Sorted runs: sorted run count for a level reaches a threshold
  • iii) File staleness: a file lives in a level for too long
  • iv) Space amplification (SA): overall SA surpasses a threshold
  • v) Tombstone-TTL: files have expired tombstone-TTL

Data layout数据布局。

image-20221207201535498

数据布局是由compaction驱动的,并通过控制­每层sorted run的数量来决定磁盘上的数据组织。compaction在存储和内存之间移动数据,消耗了设备的很大一部分带宽。因此,在ingestion(外部)和compaction(内部)之间存在着对设备带宽的内在竞争,这是对compaction的急切性(eagerness)的取舍。

数据布局通常被分为leveling和tiering。在leveling中,一旦在第i层触发compaction,标记需要compaction的文件将与第i+1层的重叠文件合并,结果被写回第i+1层,结果是,第i+1层最终会有一个(唯一的)较大不可变的文件组成的sort runs。

对于tiering来说,每个level可能包含一个以上的Key重叠的sorted run。一旦第i层的压缩被触发,第i层的所有sorted run被合并在一起,其结果作为一个新的sorted run被写入第i+1层,而不干扰该层的现有运行。Dostoevsky提出了一种混合设计,其中最后一个新的Level被实现为leveling,而磁盘上的所有剩余级别都是tiering的。在生产系统中,RocksDB将第一个磁盘层(Level 1)实现为tiering[49],并且允许它永远增长,以避免在ingestion量大的工作负载中出现write stall。

大概这里说的是rocksdb 的bulkload模式,确实有非常巨大的写入速度,但是读性能非常非常弱,CPU在读的时候爆表。

下面是是一个数据布局最常见的选项列表。

i) Leveling:每层有一次sorted run

ii) Tiering:每层有多个sorted run

iii) 1-leveling:tiering for Level 1; leveling otherwise

iv) L级:leveling for last level; tiering otherwise

v) 混合型:一个level可以是tiering压缩,也可以是leveling

image-20221207203633413

数据移动策略

当运行局部压缩时­,数据移动策略选择哪些文件进行压缩。虽然文献中通常将这种策略称为文件选择策略,但我们使用术语数据移动来概括任何可能的数据移动颗粒度。

代码里也是这么写的,叫做compaction file picker.

文件选择,一种原始的方式是随机或使用轮训策略。这两种数据移动策略并不专注于优化任何特定的性能指标,但有助于减少空间放大。为了优化读的吞吐量,许多生产型数据存储一旦触发compaction,就选择一个层中最冷的文件。另一个常见的优化目标是最小化写放大。在这个策略中,与目标层重叠最少的文件被标记为compaction。为了减少空间放大,一些存储引擎选择具有最高数量墓碑和/或更新的文件[30]。

我们遇到了类似的空间放大的问题,我选择了手动compact具有最久未compact的SSTable。引用[30] Facebook. RocksDB. github.com/facebook/ro…, 2021.好像没啥好看的啊。

另一个delete-aware的方法引入了一个墓碑年龄驱动的文件挑选­策略,旨在及时保存(timely persist)逻辑删除[51]。下面,我们介绍常见的数据移动策略的清单。

  • i) Round-robin: chooses files in a round-robin manner
  • ii) Least overlapping parent: file with least overlap with "parent"
  • iii) Least overlapping grandparent: as above with "grandparent"
  • iv) Coldest: the least recently accessed file
  • v) Oldest: the oldest file in a level
  • vi) Tombstone density: file with #tombstones above a threshold
  • vii) Tombstone-TTL: file with expired tombstones-TTLs

image-20221207211633522

我想 知道如何快速清理墓碑,Lethe论文可能真的要去看看了![51] S. Sarkar, T. I. Papon, D. Staratzis, and M. Athanassoulis. Lethe: A Tunable DeleteAware LSM Engine. In Proceedings of the ACM SIGMOD International Conference on Management of Data, pages 893ś908, 2020

compaction颗粒度

compaction粒度指的是在一次compaction工作中移动的数据量。压缩数据的一种方式是通过排序合并,并将所有数据从一个级别移动到下一个级别,我们将此称为全量压缩(full compaction).

这导致了在compaction过程中由于大数据移动,进而导致的周期性的I/O爆发­ ,随着树变高,延迟峰值加剧,导致长时间的写入停滞。为了摊薄压缩带来的I/O成本,基于水平的LSM引擎实现了局部compaction,以较小颗粒度的数据参与每次压缩,而不是全部一起。

数据的粒度可以是单个文件或多个文件,取决于系统设计和工作负载。请注意,局部compaction并不从根本上改变由于compaction而产生的数据运动总量,而是将这种数据运动均匀地随时间推移而调整,从而防止不希望出现的延迟高峰。sorted runs的compaction粒度主要适用于具有懒惰合并策略的LSM。一旦第i层的com­paction被触发,第i层的所有sorted run(或层)就会被压缩在一起,产生的条目会作为一个新的不可变的sorted run被写入第i+1层。下面是最常见的压缩粒度选项的清单。

  • i) Level: all data in two consecutive levels
  • ii) Sorted runs: all sorted runs in a level
  • iii) Sorted file: one sorted file at a time
  • iv) Several sorted files: several sorted files at a time

image.png

对现有系统的小结

image-20221207213933105

image-20221207213942275 表1:最先进系统中的compaction策略。[✓L:for levels with leveling;✓T:for levels with tiering ]