开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第32天,点击查看活动详情
[论文阅读] Lethe A Tunable Delete-Aware LSM Engine(二)
第33篇,有很多公式掘金这个编辑器没有转换好。
从本章,我们知道了传统LSM是如何处理删除的,即out-of-place删除,而后作者对一些概念做了定义,特别地:secondary deletes也就是secondary range deletes,回答删除大于7天的所有entries,这里的7天是key的额外的attribute,也即是所谓的二级删除。
至于接下来的一些量化工作,是我第一次看到关于LSM树的一些量化工作,未来可能用得上。论文来自cs-people.bu.edu/dstara/pdfs…
这一章引起了我的思考,LSM存储会逐渐变慢,例如上面说的会导致FPR增加,那么,不断update的workload是否也有这种特征,是否有低成本的监控手段去刻画这种工作负载? 没想到tiering vs leveling,其代价是不一样的,这也导致我们在为线上业务选择compaction策略时,是相当困难的!我们并不知道未来,业务的workload是如何演变的。!!!如何自适应这些workload?我想到了一个很好的idea,未来我要去读博士,可以考虑?
2. LSM背景
基础知识。 LSM-树存储键值对,其中键指的是唯一的对象标识符,而与之相关的数据则被称为值。对于关系型数据,主键作为键,而元组中的其余属性构成值。由于条目是通过键来排序和访问的,我们把它称为排序键。对于一个有L层的LSM树,我们假设它的第一层(第0层)是内存中的缓冲区,其余的层(第1层到第L层)是磁盘驻留。我们采用文献[21、50]中的符号.
插入的buffering和更新。 插入、更新或删除是在内存中缓冲的。对存在于缓冲区中的一个键的删除(更新),会就地删除(替换)旧的键,否则,删除(更新)会保留在内存中,使树的磁盘驻留部分的任何现有键的实例失效。一旦缓冲区达到其容量,条目就会按键进行排序,形成一个不可更改的sorted run,并被刷新到第一个磁盘层(第1层)。当一个盘级达到其容量时,该盘级内的所有运行被排序合并并推到下一个盘级。为了约束树中的层数,运行被安排在(容量)指数级增长的层中 在磁盘上。第i层(i≥1)的容量比第i-1层的容量大一个系数T,称为树的大小比。
compaction策略。leveling和Tiering。 传统上,LSM树支持两种合并策略:leveling和Tiering。在leveling中,每个级别最多可以有一个运行,每当第i -1级(i>=1)的运行被移到第i级时,它就会被贪婪地与第i级的运行进行排序合并,如果它存在的话。在Tiering的情况下,每一级都必须积累T个运行才会被排序合并。在排序合并(compaction)过程中,具有匹配键的条目被合并,只有最近的有效条目被保留[27, 53]。最新的混合compaction策略在一棵树中融合了leveling和tiering策略,根据不同的工作负载在读和写的吞吐量之间取得平衡[23,24]
其实是说的rocksdb默认策略。
局部compaction。 为了分摊较大级别压缩的延迟峰值,最先进的 LSM 引擎将运行组织成较小的文件,并以文件而不是级别的粒度执行压缩 [27]。如果第i级的增长超过了阈值,就会触发压缩,第i级的一个文件会被选择与第i+1级的文件进行部分压缩, 这些文件有一个重叠的关键范围。决定哪个文件要压缩取决于存储引擎的设计。例如,为了优化写吞吐量,我们从第i层选择与第i+1层的文件有最小重叠的文件,以尽量减少写放大和compaction时间。
其实这也是rocksdb的默认策略。重叠最小很重要,这是有效防止背压进而导致write stall的有效手段。
查询LSM树。 一个点查询从内存缓冲区开始,从最小的磁盘层到最大的磁盘层遍历树。对于分层,在一个层次内,查询从最近的层级移到最小的层级。当它找到第一个匹配的条目时,查找就结束了。范围查找通过排序合并树中所有运行的合格键范围来返回目标键的最新版本。
优化查询。 读取性能是通过bloomfilter(BFs)和栅栏指针来优化的。在最坏的情况下,每次运行都需要探测一次查找。为了降低这一成本,LSM引擎在主内存中的每个运行使用一个bloomfilter[21, 29]。布隆过滤器允许一个查询完全跳过探测一个sorted run,如果过滤器-查询返回负值。在实践中,为了有效存储,BFs以文件的粒度进行维护[27]。栅栏指针在内存中存储每个磁盘页的最小键[21],以快速识别要读取的查询页,并在每次运行中对点查询执行最多一次I/O。
3. 删除的影响
我们现在描述LSM树中删除的设计空间。也就是我们还能为删除做什么。
3.1 删除设计空间
在LSM树中,如果j>i,i级的条目总是比j级的相同键的条目更新。LSM树利用这一点,使用墓碑进行逻辑删除,取代了具有匹配键的旧条目。图3的左边部分显示了一个分级的LSM树,一个键值对的结构和一个墓碑。一个键值通常包含许多属性作为值的一部分,而墓碑由(删除的)键和墓碑标志组成。
3.1.1主键的删除。我们讨论排序键上的删除。 Point Deletes 在要删除的键上插入一个墓碑(图 2)。 在内存缓冲区中,墓碑会用匹配的键就地替换任何旧条目。 在磁盘上,墓碑与其他键值对一起按排序顺序存储在运行中。 在压缩过程中,墓碑会删除具有相同键的较旧条目并保留,因为在后续压缩中可能会有更多(较旧)条目具有相同的删除键(图 2)。 墓碑在与树的最后一层压缩期间被丢弃,使逻辑删除持久化。
范围删除在LSM中时常见,然而会造成性能问题。在文件中,范围墓碑被存储在一个单独的范围墓碑块中[29]。在数据访问过程中,存储被删除的范围的直方图被保存在内存中,每一个点查询都要访问它,从而减慢了read速度[15, 58]。与点删除类似,当包含它们的文件被压缩到最后一级时,范围删除就会被持久化,留下潜在的无限制的删除持久化延迟。因此,在实践中,周期性地采用完整的全树compaction来确保删除的持久性[39]。在这种compaction过程中,所有对数据存储的读和写都是停滞的,这导致了延迟高峰。
持久性延时。 持久化一个逻辑删除的延迟取决于工作负荷和数据大小。图3的中间部分展示了 "删除所有ID=k的条目 "的操作。在系统内,该操作插入了一个墓碑k ,这在逻辑上使k失效。在磁盘上,键k的条目可能在1到L的任以层因此,为了确保删除的持久性,k∗ 必须参与L个压缩,在树的每一级都有一个。由于当一个级别达到额定容量时compaction被触发了,唯一插入的速度有效地推动了compaction。一个级别的大小随T呈指数增长,因此,一个较高的树需要指数级的更多的唯一插入来传播墓碑到最后一个级别。因此,删除持久性延迟取决于(i)唯一插入率和(ii)树的当前高度。
对抗性工作负载。 墓碑可能会在树的中间层被回收,导致无限制的删除持久性延迟和无效条目的永久保留[15]。例如,一个主要修改热数据的工作负载(在前几层)将非常缓慢地增长树,使其结构基本保持静态。另一个例子是一个交错插入和删除的工作负载,删除是在最近插入的几个条目上发出的,这些条目处于较小的层次。在这两种情况下,新插入的墓碑可能会在树上高处的compaction中被回收,这些compaction会合并条目,而不是向最后一层传播。
bad case
3.1.2 二级删除 。我们把基于排序键以外的属性的删除称为二级删除 。最常见的二次删除类型是二次范围删除。考虑一下 " 删除所有超过D天的条目的操作,类似于介绍中的第二个场景。在图3的左边部分,我们强调了一个键值对的排序键(ID)和删除键(时间戳)。由于树中的条目是根据排序键进行排序的,一个具有合格的删除键的条目可能在树中的任何地方,这种删除模式没有得到有效的支持。
实际是范围删除RangeDelete
3.1.3 现有技术的局限性。
在最先进的 LSM 引擎中,删除被视为“二等公民”。 在实践中,为了确保逻辑删除的时间限制持久性并促进次级范围删除,数据存储采用定期全树压缩 [19, 39]。 然而,这是一个极其昂贵的解决方案,因为它涉及多余的磁盘 I/O,增加写入放大并导致延迟尖峰。 为了减少过多的 I/O,RocksDB 实施了一种基于墓碑 [29] 数量的文件选择策略。 这减少了无效条目的数量,但它不提供持久删除延迟保证。
3.2 out-of-place删除的影响
接下来,我们量化out-of-place删除对读取性能、空间和写入放大的影响。
这个掘金编辑器无法表述公式吗。。
模型详细信息。我们假设一个 LSM 树的大小比为 T,它在 L + 1 个级别上存储 N 个条目。 内存缓冲区的大小为 M = P·B·E,其中 P 是缓冲区中的磁盘页数,B 是每页的条目数,E 是条目的平均大小。LSM树的容量是\sum_{i=0}^LM \cdot T^i,其中M \cdot T^i是i层的容量。在树上插入的N条条目包括\delta_p点墓碑和\delta_r范围墓碑,其中平均选择性为\sigma。表1显示了我们建模中使用的所有参数。
3.2.1 空间放大。删除增加了空间放大:(i)墓碑和(ii)无效的条目(对于每个键,可能有几个无效的版本)。空间放大增加了存储成本和数据组织(分类)和处理(compaction过程中的读I/O)的开销。商业数据库通常报告说空间放大约为11%[58],然而,这相当于T*=10,是巨大设计连续体中的一个点。
分析。 根据之前的工作[23],我们将空间放大定义为多余的条目的大小与树中唯一条目的大小之间的比率,S_{amp}=\frac{csize(N)-csize(U)}{csize(U)},csize(N)是所有条目的累积大小,csize(U)是所有唯一条目的累积大小。注意到,S_{amp} \in [0,\infin),且如果所有插入的key都是唯一的,不会有空间放大。
没有删除。 假设一个分层LSM树有插入和更新(但没有删除)的工作负载。在最坏的情况下,L 1级以下的所有条目都可以成为L级的条目的更新,导致空间放大O(1/T)。对于分层LSM树,最坏的情况是当一个级别的层数重叠时,前L - 1层包含L层的更新。这导致了空间放大的O(T )。
有删除。 如果墓碑的大小与键值条目的大小相同,那么渐进的最坏情况下的空间放大率仍然与更新分级的放大率相同。然而,在实践中,墓碑要比键值条目小好几个数量级。我们引入了墓碑大小比:\lambda = \frac{size(timestone)}{size(key-value)} \approx \frac{size(key)}{size(key) + size(value)},size(key)和size(value)分别是一个key和一个条目的平均大小。\lambda的范围是(0,1],较小的 \lambda意味着几个字节(对于墓碑)可以使更多字节(对于键值)无效并导致 O(\frac{(1-\lambda)\cdot N + 1}{\lambda \cdot T})给出的更大空间放大。 对于tiering,在最坏的情况下,最近层中的墓碑会使该层中的所有条目无效,从而导致空间放大 O(\frac{N}{1-\lambda})。
3.2.2 读性能。 点墓碑以与有效键相同的方式散列到BF,因此增加了过滤器的误报率 (FPR) 以及点查找的 I/O 成本。 此外,删除的条目会导致范围查询在找到符合条件的键之前扫描无效数据。 考虑在 100GB 数据库上以 0.5% 的选择性进行范围删除会使 500MB 无效,这可能必须在查询执行期间进行扫描(并丢弃)。
分析:点查找。 在执行任何磁盘 I/O 之前,点查找会探测一个(或多个)BF。 BF 的 FPR 取决于分配给存储器中过滤器的位数 (m) 和散列到过滤器中的条目数 (N),由 e^{-m / N \cdot(ln(2))^2}给出。对于leveling,不存在条目的平均最坏情况点查找成本为O(e^{-m / N }),对于tiering,成本变为:T \cdot e^{-m / N })[21]。对于现有条目的查找,此成本增加 1,因为查找必须至少探测一页。 由于墓碑被散列到 BF 中,保留墓碑和无效条目会增加它们的 FPR,从而损害点查找。
分析:范围查找。 对排序键的范围查询读取并合并所有符合条件的磁盘页面。 访问每个级别一页的短程查询的 I/O 成本对于leveling是 O(L),对于tiering是 O(L·T)。 长范围查找的 I/O 成本取决于查找范围的选择性,对于分级是 O(s·N/B),对于分层是 O(s·T·N/B)。 在回答范围查询时,必须读取和丢弃墓碑和无效条目,从而减慢范围查询。
这一章引起了我的思考,LSM存储会逐渐变慢,例如上面说的会导致FPR增加,那么,不断update的workload是否也有这种特征,是否有低成本的监控手段去刻画这种工作负载? 没想到tiering vs leveling,其代价是不一样的,这也导致我们在为线上业务选择compaction策略时,是相当困难的!我们并不知道未来,业务的workload是如何演变的。!!!我想到了一个很好的idea,未来我要去读博士,可以考虑?
3.2.3 写放大。 在合并之前,无效条目可能会参与多次压缩。 重复压缩无效条目会增加写入放大,这对于持久存储的写入耐久性有限的安装来说尤其不受欢迎 [58]。
分析。我们定义写放大W_{amp}为未修改条目对应的写入磁盘总字节数与新条目或修改条目对应的写入总字节数的比值W_{amp}=\frac{csize(N^+)-csize(N)}{csize(N)}。N^+是写入磁盘的所有条目的数量,包括在压缩后重写为未修改的条目。 对于调平,每个条目平均参与每个级别的 T /2 压缩,这使得 N^+ = N·L·T/2。 对于分层,每个条目在每个级别写入磁盘一次,这意味着 N^+ = N·L。因此,水平和分层 LSM 树的 W_{amp}分别由 O(L·T) 和 O(T) 给出。 请注意,随着数据大小的增加,条目参与更多未修改的压缩,包括无效条目进一步增加写入放大。
3.2.4 持久性延迟和数据隐私。 缺乏持久性延迟保证对数据隐私有严重影响。 随着新的数据隐私保护法案 [1, 34] 和对被遗忘权等权利保护的加强,数据公司在法律上有义务持续删除数据提供保证 [26] 并重新考虑端到端数据 生命周期[60]。
分析。 我们将删除持久性延迟定义为插入墓碑后所需的最坏情况时间,以确保树中没有任何具有与墓碑键匹配(较旧)键的条目。 这个时间取决于唯一键值条目的插入率(I)和树的高度(L-1),并且是插入足以触发足够压缩的最小数量的唯一键所需的时间。对于均衡,删除持久性延迟为 O(\frac{T^{L-1} \cdot P \cdot B}{I}),对于分层为 O(\frac{T^{L} \cdot P \cdot B}{I})。这表明对于由更新密集型工作负载构建的具有大量条目 (T^L) 的 LSM 树,删除持久性延迟可能非常高。
存储布局的含义
LSM-tree 的每个文件都使用排序键进行排序。 虽然这支持对排序键的读取、更新和删除查询,但它不支持对次要属性的操作。 对与排序键不同的删除键的次级范围删除只能通过急切地执行完整的树压缩来支持,因为无法识别受影响的文件。 这会停止所有写操作,导致巨大的延迟峰值。
二级范围删除产生的成本取决于磁盘上数据页的总数,并且与范围删除操作的选择性无关。 无论采用何种合并策略,此成本都是 O(N/B),其中 B 是页面大小。