开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情
论文阅读: Constructing and Analyzing the LSM Compaction Design Space(二)
表1:最先进系统中的compaction策略。[✓L:for levels with leveling;✓T:for levels with tiering ]
上一篇文章juejin.cn/post/717439…发了一个很好的图。系统分类了最先进的LSM系统的compaction策略,我们来看看RocksDB的分类:
RocksDB支持1-leveling、Tiering ompaction策略。1-Lvl代表了一种混合数据布局,其中第一个磁盘层被实现为tiering,而其他的则是leveling。这是RocksDB的默认数据布局。
通常文件是否过于陈旧(支持compaction ttl配置),对应层级是否饱和,将以单个文件、多个文件粒度方式触发compaction,当compaction时,一个较好的目标子集是较少与父,祖父重叠的文件。上图还提到RocksDB支持及时compact掉墓碑。但我没有找到类似调优选项。
每个compaction策略都为四个原语中的一个或多个值。触发器、颗粒度和数据移动策略是多值原语,而数据布局是单值的。
例如,一个常见的LSM设计[2]有一个分级的LSM树(数据布局),一旦一个级别达到额定大小(触发器) ,就会一次压缩整个层级(颗粒度)。这种设计没有实现许多微妙的优化,包括局部compaction,而且根据定义,不需要数据移动策略。一个更复杂的例子是一个Tiering LSM树(数据布局)的compaction策略,其中compaction是以文件的粒度进行的。如果
(a)一个级别达到了它的容量,
b)一个包含墓碑的文件在一个级别中的停留时间超过了预先设定的TTL
就会触发compaction 。一旦触发,数据移动策略会选择(a)墓碑密度最高的文件(如果有的话 ) 或(b)与父级的重合度最低的墓碑密度最高的文件。
compaction设计空间的基数 如果两个compaction策略在四个原语中至少有一个不同,那么它们就被认为是彼此不同的。仅在一个原语上有差异的compaction策略,在相同的硬件上运行时,面对相同的工作负载,其性能会有很大的不同。插入原语的一些典型值,我们估计压缩的原语数大于10^4 ,这是一个巨大的但在很大程度上尚未开发的设计空间。表1显示了这个空间的一个代表性部分,详细说明了20多个学术和生产系统中使用的压缩策略。
分析compaction:下表选择10个有代表性的compaction策略:
-
full 代表全量compact
-
LO+1和LO+2表示两个partial compaction,分别选择一个与父级(i +1)和祖父级(i +2)文件重叠度最小的文件进行compaction。
-
RR以轮训的方式从各层选择文件进行压缩。
-
Cold和Old是read友好的策略,分别标记一个级别中最冷和最老的文件进行压缩。
-
TSD和TSA是删除驱动的compaction策略,具有触发器和数据移动策略,分别由墓碑的密度和文件中最老的墓碑的年龄决定。
-
Tier代表了tiering数据布局的一个变种,当(a)一个层次中的分类运行数量或(b)树中的估计空间放大达到一定的阈值时,就会触发compaction。RocksDB等系统中也被称为universe compaction。
-
1-Lvl代表了一种混合数据布局,其中第一个磁盘层被实现为tiering,而其他的则为leveling。这是RocksDB的默认数据布局。
benchmarking compaction
这里选择了使用rocksdb作为实验平台这很棒。作者在rocksdb中实现了所有compaction策略!集成到RocksDB v6.11.4中。为compaction工作分配了比写入工作更高的优先级(这句话不太理解,要看看代码做了哪些取舍),以便准确地进行*compaction。
作者开源了本文的代码,github.com/dongdongwcp…,这是一个极好的学习机会,作者也列出来几个修改的地方:有机会要细读下代码,这个compaction策略可以必要时调整。
性能指标:compaction延迟(Compaction Latency)
compaction延迟包括以下时间:
(i)确定要compaction的文件,
(ii)将参与的文件读到内存中,
(iii)对文件进行排序-合并(并删除重复部分)文件,
(iv)将结果作为新的文件写回磁盘,
(v)使旧文件无效
(vi)更新清单文件中的元数据[30]。
RocksDB的rocksdb.compaction.times.micros被用来衡量compaction延迟的情况。
写放大(WA)。 由于compaction引起的重复读写导致了高的WA。我们将WA正式定义为一个条目在其生命周期内被(重新)写入磁盘而没有任何修改的次数 。 我们使用RocksDB的指标compact.write.bytes和实际数据大小来计算WA。
WA的正式定义
写入延时: 写入延迟是由设备的带宽利用率驱动的,它取决于(i)由于compaction而造成的write stall和(ii)由于设备的带宽利用率而造成的write stall。(ii) 持续恒定的设备带宽。我们使用db.write.micros直方图来测量写延迟的平均值和尾部。
读取放大率(RA): RA是指用于点查询的磁盘页的总数量 ber与应读页之间的比率。是理想的读取方式。我们使用rocksdb.byte.read来计算RA。
点查询的延迟: compaction决定了文件在LSM树中的位置,这影响了对这些文件中包含的条目的点查询。这里,我们使用db.get.micros直方图。
范围查找延时:范围查询延迟取决于范围查询的选择,但也受到数据布局的影响。我们也使用db.get.micros直方图进行范围查询。
难道不是db.seek.micro延迟吗?
空间放大(SA): SA取决于数据布局、compaction粒度和数据移动策略。SA被定义为逻辑上无效的条目的大小与树中唯一条目的大小之间的比率。我们使用数据库的大小和逻辑有效条目的大小来计算SA。
删除性能: 我们衡量测试的compaction策略在限制时间内持续删除条目的程度,以便从隐私的角度分析compaction的影响。我们使用RocksDB的file metadata age和删除持久性阈值。
benchmark测试方法
工作负载:一个典型的键值工作负载包括五个主要操作:插入、更新、点查、范围查询和删除。点询的目标是数据库中可能存在或不存在的键,我们将其分别称为非空点查和空点查。
范围查找的特点是其选择性。为了分析每个操作的影响,我们改变了每个操作的比例以及它们的质量特征(即选择性和条目大小)。我们进一步改变ingestion和查询的数据分布,重点是(i)均匀分布,(ii)正态分布,和(iii)Zipfian分布。
总的来说,我们定制的基准测试套件是有影响力的YCSB基准[19]以及insert基准[15]的超集,并支持一些现有工作负载生成器中缺少的参数,包括删除。我们的工作负载生成器暴露了超过64个自由度,并可通过GitHub[52]进行传播、测试和采用。
LSM调谐。 我们进一步研究LSM调整和compaction策略的相互作用。我们考虑的问题是,对于特定的LSM设计和给定的工作负载,哪种压缩策略是合适的? 为了回答这些问题,我们在实验中改变了关键的LSM调整参数,如(i)内存缓冲区大小,(ii)块缓存大小,以及(iii)树的大小比例。
细看这篇文章,作者开源了代码,我们可以进一步学习对rocksdb的修改很compaction的集成测试,并尝试在自己的系统中测试某种符合自己预期compaction 策略。