开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第31天,点击查看活动详情
🗡Lethe:delete Awared LSM
虽然LSM在写和读方面都很出色,但作者研究发现:所有基于LSM的数据存储在删除的工作负载中表现并不理想。
LSM树中的删除行为
LSM树中的删除是通过插入一种特殊类型的key-value条目(称为墓碑)来实现的逻辑上的删除。一旦插入,墓碑就会在逻辑上使树中所有具有匹配key的条目失效,而不一定会干扰物理目标数据条目。只有在相应的墓碑通过compaction达到树的最后一层后,目标条目才会从数据存储中持久性地删除。持久化删除目标条目所需的时间取决于(i)compaction 轮次中的文件拣选策略,(ii)数据库ingestion条目的速度,(iii)LSM-树的大小比例,以及(iv)树中的层数。
上图显示了墓碑驱动的逻辑删除是如何持久化的,举个例子,我们想从一个基于LSM的数据存储中删除所有key为6的条目。在步骤1中,一个6的墓碑,用6表示,被插入到树中。第2步,显示了由于(局部)compaction,包含墓碑6的文件是如何移动到树的下一级的。最后,第3步显示了在墓碑到达树的最后一层后,6终于被LSM彻底删除。
问题
所有先进的LSM引擎都将删除视为 "二等公民"。目前在逻辑上实现删除的out-of-place机制对数据存储的整体性能和隐私边界都有影响。
主键删除:排序key上的删除
正如所讨论的,在排序key上的删除,也就是key-value条目的 "key",是通过插入针对要删除的key的墓碑来实现。这样做的问题有以下几点。
首先,在树中保留无效的条目(连同墓碑)会导致磁盘空间的误用,从而导致空间放大。
第二,树中的无效条目在compaction过程中被反复写入,导致写放大。这个问题很大。
第三,由于无效条目(和墓碑)仍然被哈希到布隆过滤器中,在固定的内存预算下,它们增加了过滤器的假阳性率,这导致了渐进式的更差的读取性能。
最后,由于对持久性删除数据对象所需的时间没有约束,out-of-delete删除策略可能导致持久性删除的延迟非常高,这是一个严重的隐私问题。
作者还漏了一个更重要的影响,也就是范围查询会骤慢,在rocksdb上的表现为rocksdb.number.skipped.count数量急剧增加,无论CPU&内存都被放大。
Secondary deletes:在排序key以外的属性上进行删除
对一个不同于排序key的属性的删除被称为二级删除。二级范围删除操作,也就是基于secondary 属性地删除一个区间范围的entries,在某些实际工作负载中也很频繁。
如下图中:secondary deletes也可以理解为:删除所有超过D天的条目。
现代基于LSM的数据存储无法有效地实现二级范围删除,因为符合这种操作条件的条目可能分散在整个树上。商业数据存储实现二级范围删除操作的方式是定期(通常是每7天、15天或30天)将整棵树压缩到一个基本级别。这样的全树压缩是非常不可取的,因为它们需要许多多余的I/O到磁盘上,也可能导致长时间的写入停顿和延迟高峰。在这里的例子中,我们用S表示排序key,用D表示删除key,我们观察到,为了实现二级范围的删除操作,删除所有时间戳小于66的条目,所有显示的四个页面,必须读到内存中。
解决方案。Lethe = FADE + KiWi
为了解决上述与LSM树中的删除相关的问题,我们引入了Lethe。Lethe的目的是(i)为主要的删除操作提供持久性保证,(ii)在LSM树中实现高效的二级范围删除。
FADE: FAst DEletes
无语,我一直以为FADE是file age or delete entry count的删除策略。原来是 ,fast deletes。
为了实现第一个设计目标,我们引入了FADE,这是一个删除感知compaction策略系列,确保所有的墓碑都在一个删除持久性阈值内被持久化。FADE使用关于文件中包含的墓碑的年龄和每个墓碑的估计无效条目的额外信息来确保LSM树中的所有墓碑都在用户/应用设置的阈值内被持久化。FADE通过使用删除持久化阈值来为树的每一层分配一个生存时间来实现这一目标。现在,如果在任何时候,包含墓碑的文件的年龄超过了level-TTL,FADE就会启动一个compaction。
请注意,这个compaction触发器与基于饱和度的触发器是完全正交的,它由文件中包含的大墓碑的年龄驱动。这样,FADE保证了及时的删除持久性,并且通过及时和持久地从树上删除无效的条目,FADE也提高了存储引擎在删除时的整体性能。上图逐步显示了FADE是如何通过为未来的compaction作业设置更早的最后期限来保证及时的删除持久性。
KiWi: Key Weaving Storage Layout
为了促进关于二级范围删除的第二个设计目标,我们引入了KiWi,这是一个连续的物理存储布局,将磁盘上的数据按照排序key和删除key的交织排序顺序排列。KiWi支持二级范围删除,而不执行全树压缩,代价是最小的额外元数据和可调整的代价read性能。
KiWi在LSM树的存储布局中增加了一个新的层次。特别是,除了树的层次、一个层次的文件和一个文件的页之外,我们现在引入了属于一个文件并由页组成的delete tiles。一个delete tiles是一个文件中连续页面的逻辑集合。在一个delete tiles中,条目被划分在删除keyD上,并被分割成页。这样一来,通过在D上对条目进行排序,KiWi就可以将符合条件的条目集中起来进行二级范围删除。这反过来又使KiWi能够以较少的磁盘I/O为代价进行二级范围删除。在查找过程中,为了便于在页面内进行严格的二分搜索,KiWi会对排序keyS上的条目重新排序,如上图所示。
这就是类似rangeDelete的另个实现?还有另一张图:
结果
Lethe将FADE和KiWi的优势结合起来,更好地支持LSM树中的删除。对于给定的工作负载和持久性删除延迟阈值,Lethe通过仔细调整持久性删除的成本,以及它们对系统整体性能的影响,提供了最大的性能。我们将Lethe与最先进的LSM树设计相比较,对一系列带有删除和不同删除持久性阈值的工作负载进行评估。
评估FADE
在下面的实验中,我们在数据库中插入1GB的数据(平均条目大小=1KB)。内存缓冲区的大小为1MB,树的大小比例为10。删除持久性阈值被设置为实验运行时间的16.67%、25%和50%。
图(A)显示,Lethe确保了及时的持久性删除。与RocksDB相比,Lethe多坚持了40%到80%的墓碑,而且它是在遵守删除持久性阈值的情况下做到的。图(B)显示,Lethe通过及时持久化删除大大减少了空间放大。图(C)显示,与RocksDB相比,Lethe通过以有时限的方式清除无效条目,提供了更好的读取性能,从而提高了Bloom过滤器的准确性。
评估KiWi
在以下实验中,工作负载包括0.001%的二级范围删除操作,以及1%的范围查询和50%的点查询。每个文件有256页,每页的大小为4KB。
图(D)显示,较高的删除瓦片颗粒度增加了全页下降的数量,从而减少了数据存储在KiWi中时的I/O。图(E)显示,不同的删除瓦片颗粒度对不同的工作负载来说是最佳的。Lethe可以通过确定最佳存储布局来驾驭存储布局的连续性,并提供卓越的整体性能。图(F)显示了Lethe和RocksDB在不同的删除瓦片大小时在散列和I/O访问方面所花费的总时间。Lethe计算出h的最佳值,在这种情况下是8。对于h=8,Lethe的I/O成本比RocksDB的低76%。这是以散列成本增加5倍为代价的,然而,这完全隐藏在I/O总数的巨大好处背后。
结论
最先进的基于LSM的key-value存储对于有小部分删除的工作负载来说表现并不理想,而且这些数据存储中的删除持久化延迟可能是无界的。为了解决这个问题,我们建立了Lethe,一个新的基于LSM的引擎,引入了一个新的压缩策略系列FADE和KiWi,一个连续的物理数据存储布局。FADE在用户定义的阈值内强制执行删除持久性,同时增加读取吞吐量并减少空间放大,代价是适度增加写入放大。KiWi提供了高效的二级范围删除,可以对其进行调整,使其在特定的工作负载中的表现优于现有技术水平。据我们所知,Lethe是第一个基于LSM的存储引擎,它提供高效的删除,对读取性能没有干扰或有干扰,支持用户定义的删除延迟阈值,并能实现实用的二级范围删除。