LSM-based Storage Techniques: A Survey(2019)

(一)研究目的

总结关于lsm-tree的研究成果。

(二)LSM-tree基础

2.1 LSM-tree历史

通常,索引结构可以从两种策略中选择一种来处理更新,即就地更新和非就地更新。一个就地更新结构,比如B+树,直接覆盖旧记录来存储新的更新。这些结构通常是读优化的,因为只存储每个记录的最新版本。但是,这种设计牺牲了写性能,因为更新会产生随机I/o。此外,索引页可以通过更新和删除进行分片,从而降低空间利用率。
相比之下,非就地更新结构(如lsm-tree)总是将更新存储到新的位置,而不是覆盖旧的条目。这种设计提高了写性能,因为它可以利用顺序I/o来处理写。它还可以通过不覆盖旧数据简化恢复过程。但是,这种设计的主要问题是牺牲了读取性能,因为一条记录可能存储在多个位置中的任何一个。此外,这些结构通常需要一个单独的数据重组过程,以不断提高存储和查询效率。
在使用lsm -树之前,日志结构存储的方法存在几个关键问题。首先,将数据存储到仅追加日志中会导致较低的查询性能,因为相关记录分散在日志中。
另一个问题是空间利用率低,这是因为还没有删除过时的记录。尽管设计了各种数据重组过程,但没有一个有原则的成本模型来分析写成本、读成本和空间利用率之间的权衡,这使得早期的日志结构存储难以调优;数据重组很容易成为性能瓶颈。
1996年提出的LSM-tree通过设计一个合并过程来解决上述问题,提出的滚动合并流程由于其实现的复杂性,目前基于lsm的存储系统不使用它。在稳定的工作负载下,层数保持不变,当所有相邻组件的大小比Ti = |Ci+1|/|Ci|保持一致时,写性能得到优化。这一原则影响了lsm-tree的所有后续实现和改进。
同时Jagadish等人提出了一种类似的结构,并带有分步合并策略,以获得更好的写性能。这个策略成为今天LSM-tree实现中使用的分级合并策略

2.2 如今的LSM-tree

2.2.1 基本结构

  • 追加写
  • 内存里的数据结构是跳跃表或B+tree,磁盘上的数据结构是B+tree或sorted-string tables(SSTables)
  • 查询从新到旧
  • 水平合并策略 or 分级合并策略

2.2.2 两种有名的优化

Bloom FilterPartitioning
Bloom filter 是一种节省空间的概率数据结构,用于辅助查询。
分区将一个较大的组件合并操作分解为多个较小的操作,从而限制每个合并操作的处理时间以及创建新组件所需的临时磁盘空间。通过只合并具有重叠键范围的组件,分区可以优化具有顺序创建键或倾斜更新的工作负载。
只有基于lsm的工业存储系统(如LevelDB和RocksDB)完全实现了分区均衡策略。一些论文提出了各种形式的分区分级合并策略,以获得更好的写性能。
垂直分组方案和水平分组方案:
在这里插入图片描述在这里插入图片描述

2.2.3 并发控制与恢复

对于并发控制,lsm-tree 需要处理并发的读和写,并处理并发的刷新和合并操作。根据事务隔离需求的不同,使用 锁模式 or 多版本模式

(三)LSM-tree改进

提出了一种分类法,对改进LSM-tree的现有研究工作进行分类。

3.1 改进LSM-tree的分类

  • Write Amplification:水平合并策略仍然会带来相对较高的写放大,写放大程度高不仅限制了LSM-tree的写性能,而且由于频繁使用硬盘,会导致ssd盘寿命缩短。
  • Merge Operations:合并操作可能会导致缓冲区缓存丢失和大型合并期间的写入停顿。
  • Hardware:大量研究致力于改进lsm-tree,以充分利用底层硬件平台,包括大内存、多核、SSD/NVM和本地存储。
  • Special Workloads:利用这些特殊工作负载所显示的独特特征。
  • Auto-Tuning:基于RUM猜想,任何访问方法都不能同时是读最优、写最优和空间最优。lsm-tree可能很难调优,因为有太多的调优旋钮,比如内存分配、合并策略、大小比例等。
  • Secondary Indexing:为了支持对非键属性的查询的高效处理,必须维护辅助索引。这个领域的一个问题是如何以较小的写性能开销有效地维护一组相关的二级索引。
    在这里插入图片描述

3.2 减少写放大

这些改进大部分是基于分层的,因为它比水平有更好的写性能。其他提出的改进已经开发了执行合并跳过或利用数据倾斜的新技术。

3.2.1 Tiering

优化写放大的方法是分层,它的写放大比分级低。

  • WriteBuffer (WB) Tree
  • light-weight compaction tree (LWC-tree)
  • PebblesDB
  • dCompaction
  • 。。。

3.2.2 Merge Skipping

  • skip-tree:提出了一个合并跳过的想法,以提高写性能。

3.2.3 Exploiting Data Skew

  • TRIAD:减少了频繁更新某些热键的倾斜更新工作负载的写放大。

3.3 优化合并操作

改进合并操作实现的现有工作,包括改进合并性能、最小化缓冲区缓存误检以及消除写暂停。

3.3.1 提高合并性能

  • VT-tree提出了一种拼接操作来提高合并性能。
  • Zhang等人提出了一种流水线合并实现,以更好地利用CPU和I/O并行性来提高合并性能。

3.3.2 减少缓存丢失

合并操作可能会干扰系统的缓存行为。合并操作消耗大量CPU和I/O资源,并在查询响应时间上施加了很高的开销。为了解决这个问题,本文建议将大型合并转移到远程服务器,以最大限度地减少它们的影响。在合并操作完成后,将使用智能缓存预热算法增量地获取新组件,以减少缓冲区缓存丢失。其思想是逐步地、逐块地切换到新组件,以便顺利地将传入的查询从旧组件重定向到新组件。这样一来,缓冲区缓存丢失的爆发就被分解为大量较小的缓存丢失,从而将组件切换对查询性能的负面影响降到最低。

3.3.3 最小化写停顿(write stall)

虽然与传统的B+tree相比,lsm-tree提供了更高的写吞吐量,但因为刷新和合并等繁重操作在后台运行,它经常表现出写停顿和不可预测的写延迟。
bLSM提出了一个弹簧-齿轮合并调度程序来最小化未分区均衡合并策略的写阻塞。它的基本思想是在每个级别上容忍一个额外的组件,以便在不同级别上的合并可以并行进行。

3.4 硬件的机会

针对不同硬件平台提出的lsm-tree改进,包括大内存多核SSD/NVM本地存储。这些改进的一般范式是修改lsm-tree的基本设计,以充分利用目标硬件平台提供的独特特性,以实现更好的性能。

3.4.1 大内存

对于lsm-tree来说,使用较大的内存组件来减少层级的总数是有益的,因为这将提高写性能和查询性能。然而,管理大内存组件带来了一些新的挑战。如果直接使用堆上数据结构实现内存组件,则大内存可能导致大量小对象,从而导致大量GC开销。相反,如果内存组件使用非堆结构(如并发B+树)实现,那么大的内存仍然会导致更高的搜索成本(由于树的高度),并导致更多的CPU缓存写操作失败,因为写操作必须首先搜索它在结构中的位置。
FloDB采用两层设计来管理大内存组件。顶层是一个小型的并发哈希表,以支持快速写入,而底层是一个大型的跳表,以高效地支持范围查询。当哈希表已满时,它的条目将使用批处理算法有效地迁移到跳表中。通过将随机写入限制在很小的内存区域,这种设计显著提高了内存中的写入吞吐量。为了支持范围查询,FloDB要求范围查询必须等待哈希表被抽干,以便可以单独搜索跳表来回答查询。然而,FloDB存在两个主要问题。首先,它对于同时包含写查询和范围查询的工作负载来说效率不高,因为它们存在争用。其次,跳表可能占用较大的内存,从而导致较低的内存利用率。

3.4.2 多核

cLSM针对多核计算机进行了优化,并为各种lsm树操作提供了新的并发控制算法。它将LSM组件组织成一个并发链表,以尽量减少同步引起的阻塞。

3.4.3 SSD/NVM

与传统硬盘只能支持高效的顺序I/o不同,ssd、nvm等新型存储设备也可以支持高效的随机I/o。nvm进一步提供了有效的字节寻址随机访问,并提供持久性保证。
FD-tree使用与lsm-tree类似的设计来减少对ssd的随机写操作,一个主要的区别是fd-tree利用分数级联而不是Bloom过滤器来改进查询性能。
FD+tree改进了FD-tree的合并过程。在FD-tree中,当从级别0到级别L发生合并时,必须在级别0到L创建新的组件,这将临时增加两倍的磁盘空间。为了解决这个问题,在合并操作期间,FD+tree递增地激活新组件,并从任何活动查询不使用的旧组件回收页面。
MaSM旨在通过利用ssd来支持数据仓库工作负载的高效更新。MaSM首先将所有更新缓存到SSD中,采用分级合并策略,合并写扩增较低的中间组件,然后将更新合并回驻留在硬盘中的基本数据。

由于 ssd 支持高效的随机读取,将值与键分离成为提高 lsm-tree 写性能的可行解决方案。该方法首先由 WiscKey 实现,随后由 HashKV 和 SifrDB 采用。

Kreon利用内存映射I/O,通过避免不必要的数据复制来减少CPU开销。它在Linux内核中实现了一个定制的内存映射I/O管理器,以控制缓存替换和启用盲写。为了提高范围查询的性能,Kreon在查询过程中通过将访问过的键值对存储在一个新的位置来重新组织数据。

NoveLSM是一个在nvm上实现lsm-tree的程序。NoveLSM添加了一个基于nvm的内存组件,以便在DRAM内存组件满时提供写操作,这样写操作仍然可以继续,而不会停止。它通过skipping logging进一步优化了NVM内存组件的写性能,因为NVM本身提供了持久性。最后,它利用I/O并行性并发搜索多个级别,以减少查找延迟。

3.4.4 本地存储

LOCS是开放通道ssd上lsm-tree的一种实现。
NoFTL-KV提出将存储设备中的flash转换层(FTL)提取到键值存储中,从而获得对存储设备的直接控制。

3.5 处理特殊的工作负载

特殊的工作负载包括临时数据、小数据、半排序数据和以附加数据为主的数据。

log-structured history access method (LHAM) 改进了原来的lsm-tree,以更有效地支持临时工作负载。LHAM所做的关键改进是将时间戳范围附加到每个组件上,通过修剪不相关的组件来方便处理时间查询。

LSM-trie 是一个基于lsm的哈希索引,用于管理大量的键值对,其中每个键值对都很小。它提出了许多优化,以减少元数据开销。LSM-trie采用分区分层设计,以减少写放大。LSMtrie不是直接存储每个SSTable的键范围,而是使用它们的哈希值的前缀来组织它们的SSTable,以减少元数据开销。

SlimDB 针对的是半排序数据,其中每个键都包含一个前缀x和一个后缀y。

3.6 自动调节

有些技术对所有参数进行协同调优,以找到最佳设计,而其他技术则专注于某些特定方面,如合并策略、Bloom过滤器或数据放置。

3.6.1 参数调优

Lim等人提出了一个分析模型,该模型结合了关键分布来改善lsm-tree操作的成本估计,并进一步使用该模型来调整lsm-tree的参数。

Monkey协同调整合并策略、大小比例和内存组件和Bloom过滤器之间的内存分配,以找到给定工作负载的最优lsm-tree设计。

3.6.2 调优合并策略

Dostoevsky表明,现有的合并策略(即分级和均衡)对于某些工作负载不是最优的。零结果点查找、远程查询和空间放大的开销主要来自于最大级别,但是所有级别的写入开销都是相同的。为了解决这个问题,引入了一个惰性均衡合并策略,该策略在较低级别执行分级,但在最大级别执行均衡。

3.6.3 动态Bloom过滤器内存分配

现有的LSM-tree实现,都采用静态方案来管理Bloom过滤器内存分配。
ElasticBF根据数据热度和访问频率动态调整Bloom filter的误报率,以优化读性能。

3.6.4 优化数据放置

Mutant 优化了LSM-tree在云存储上的数据放置。

3.7 二级索引

前面的讨论仅包含单个lsm树的键值存储设置中的lsm树改进。下面讨论基于lsm的二级索引技术,以支持高效的查询处理,包括索引结构、索引维护、统计信息收集和分布式索引。

通常,基于lsm的存储系统将包含一个主索引和多个从索引。主索引存储按主键索引的记录值。每个二级索引使用组合键方法或键列表方法存储每个辅助键的相应主键。

3.7.1 索引结构

Log-Structured Inverted Index 是一种针对microblogs实时关键字精确搜索而设计的索引结构。

3.7.2 索引维护

维护基于lsm的二级索引的一个关键是处理更新。

3.7.3 统计搜集

Absalyamov等人为基于lsm的系统提出了一个轻量级统计收集框架。基本思想是将统计信息收集任务集成到刷新和合并操作中,以最小化统计信息维护开销。

3.7.4 分布式索引

(四)代表性LSM系统

五个具有代表性的基于lsm的开源NoSQL系统:LevelDB、RocksDB、Cassandra、HBase和AsterixDB。

4.1 LevelDB

LevelDB的主要贡献是它首创了分区水平合并策略的设计和实现。

4.2 RocksDB

RocksDB的LSM-tree实现仍然基于分区层级设计,但有一些改进。

由于0级的SSTable是没有分区的,将一个SSTable从0级合并到1级通常会重写1级的所有SSTable,这通常会使0级成为性能瓶颈。为了部分解决这个问题,RocksDB有选择地使用分级合并策略在0级合并sstable。这种弹性设计允许RocksDB更好地吸收写突发,而不会过多地降低查询性能。RocksDB进一步支持动态层级大小方案来约束空间放大。
RocksDB还支持两个附加策略:cold -first和delete-first。
除了支持分区均衡合并策略外,RocksDB还支持分级、FIFO等合并策略。

4.3 HBase

Apache HBase是Hadoop生态系统中的分布式数据存储系统;它是模仿谷歌的Bigtable设计。HBase是基于主从架构的。
HBase的LSM-tree实现通常基于基本的分级合并策略。它还支持分级合并策略的一些变体,例如探索合并策略和日期分级合并策略。

4.4 Cassandra

Apache Cassandra 是一个开源的分布式数据存储系统,模仿了Amazon的Dynamo和谷歌的BigTable。
Cassandra依靠一个分散的架构来消除单点故障的可能性。Cassandra中的每个数据分区都由一个基于lsm的存储引擎支持。

Cassandra支持一组与RocksDB和HBase类似的合并策略,包括(未分区)分级合并策略、分区均衡合并策略和日期分级合并策略。此外,Cassandra还支持本地二级索引,以方便查询处理。为了避免高点查找开销,二级索引是惰性维护的,类似于DELI。在更新期间,如果在内存组件中找到旧记录,则使用它直接清理二级索引。否则,在合并主索引组件时,二级索引会被惰性地清理。

4.5 AsterixDB

Apache AsterixDB是一个开源的大数据管理系统(BDMS),旨在高效地管理大量的半结构化(如JSON)数据。

(五)未来研究方向

全面的性能评估

如前所述,迄今为止,在许多研究工作中,lsm树的可调性没有得到充分的考虑。改进工作通常会根据LevelDB或RocksDB的默认(未调优的)配置进行评估。目前还不清楚对于给定的工作负载,这些改进将如何与调优的基线lsm-tree进行比较。此外,许多改进建议主要评估了它们对查询性能的影响,而空间利用率常常被忽略。这种情况可以在未来的研究中通过更仔细地考虑lsm-tree的可调性来解决。

分区分层结构

分层已被许多lsm-tree改进所使用,以减少lsm-tree的写扩增。已经确定的两种可能的分级方案,即水平分组和垂直分组,它们几乎涵盖了最近提出的所有与分级相关的lsm-tree改进。然而,这两种方案的性能特点和权衡还不清楚。一般来说,垂直分组允许更多的自由选择sstable来合并,而水平分组确保sstable是固定大小的。对这两种方案进行系统的评价,并结合两种方案的优点设计新的方案,对今后的工作具有一定的指导意义。

混合合并策略

大多数lsm-tree改进都假定了在lsm-tree的所有级别上进行平级或分层的同质合并策略。但是,这对于某些工作负载来说不是最优的。水平和分层的混合合并策略可以提供比水平更好的写性能,同时对点查找、远程查询和空间放大的影响最小。作为一个未来的方向,设计和实现具有混合合并策略的lsm-tree并重新考虑这种设计选择所提出的一些关键问题将是有趣的.

最小化性能差异

在实践中,性能差异与绝对吞吐量一样重要。不幸的是,lsm树经常表现出很大的性能差异,因为它们将内存中的写操作与昂贵的后台I/o解耦。正如我们在这次调查中所看到的,bLSM是最小化lsm-tree所展示的写入停顿的唯一尝试。然而,bLSM本身仍然有一些局限性。它是专为未分区的水平合并策略设计的,并且它只会最小化由写暂停引起的长写延迟,而不是减小总体吞入吞吐量的差异。在未来的工作中,设计一种最小化lsm树性能差异的机制将是非常有用的。

应用于数据库存储引擎

大多数现有的lsm-tree改进都集中在涉及单个lsm-tree的键值存储设置上。随着lsm-tree在DBMS存储引擎中逐渐被广泛使用,应该为这种更通用的(多索引)设置开发新的查询处理和数据摄取技术。可能的例子包括辅助结构的自适应维护以促进查询处理、支持lsm的查询优化,以及将lsm树维护任务与查询执行联合规划。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值