欢迎来到飞鸟慕鱼博客,开始您的技术之旅!
当前位置: 首页知识笔记正文

网络信息安全中的安全策略模型包括了建立安全环境的3个重要组成部分分别是健全,李世石与好友通宵研究下棋策略

终极管理员 知识笔记 91阅读

拆开成为多个key互不相交的的序列这样的序列叫做“run”。L0层是从memtable flush过来的新SST该层各个SST的key是可以相交的并且其数量阈值单独控制如4。从L1层开始每层都包含恰好一个run并且run内包含的数据量阈值呈指数增长。

下图是假设从L1层开始每个的大小都相同在实际操作中不会强制要求这点且数据量阈值按10倍增长的示例。即L1最多可以有10个SSTL2最多可以有100个以此类推。

随着SST不断写入L1的数据量会超过阈值。这时就会选择L1中的至少一个SST将其数据合并到L2层与其key有交集的那些文件中并从L1删除这些数据。仍然以上图为例一个L1层SST的key区间大致能够对应到10个L2层的SST所以一次compaction会影响到11个文件。该次compaction完成后L2的数据量又有可能超过阈值进而触发L2到L3的compaction如此往复就可以完成Ln层到Ln1层的compaction了。

可见leveled compaction与size-tiered compaction相比每次做compaction时不必再选取一层内所有的数据并且每层中SST的key区间都是不相交的重复key减少了所以很大程度上缓解了空间放大的问题。重复一遍上一节做的两个实验曲线图分别如下。

持续写入实验尖峰消失了。

持续更新实验磁盘占用量的峰值大幅降低从原来的9.3GB缩减到了不到4GB。

但是鱼与熊掌不可兼得空间放大并不是唯一掣肘的因素。仍然以size-tiered compaction的第一个实验为例写入的总数据量约为9GB大但是查看磁盘的实际写入量会发现写入了50个G的数据。这就叫写放大write amplification问题。

写放大又是怎么产生的呢下面的图能够说明。

可见这是由compaction的本质决定的同一份数据会不断地随着compaction过程向更高的层级重复写入有多少层就会写多少次。但是我们的leveled compaction的写放大要严重得多同等条件下实际写入量会达到110GB是size-tiered compaction的两倍有余。这是因为Ln层SST在合并到Ln1层时是一对多的故重复写入的次数会更多。在极端情况下我们甚至可以观测到数十倍的写放大。

写放大会带来两个风险一是更多的磁盘带宽耗费在了无意义的写操作上会影响读操作的效率二是对于闪存存储SSD会造成存储介质的寿命更快消耗因为闪存颗粒的擦写次数是有限制的。在实际使用时必须权衡好空间放大、写放大、读放大三者的优先级。

RocksDB的混合compaction策略

由于上述两种compaction策略都有各自的优缺点所以RocksDB在L1层及以上采用leveled compaction而在L0层采用size-tiered compaction。下面分别来看看。

leveled compaction

当L0层的文件数目达到level0_file_num_compaction_trigger阈值时就会触发L0层SST合并到L1。

L1层及以后的compaction过程完全符合前文所述的leveled compaction逻辑如下图所示很容易理解。

多个compaction过程是可以并行进行的如下图所示。最大并行数由max_background_compactions参数来指定。

前面说过leveled compaction策略中每一层的数据量是有阈值的那么在RocksDB中这个阈值该如何确定呢需要分两种情况来讨论。

参数level_compaction_dynamic_level_bytes为false
这种情况下L1层的大小阈值直接由参数max_bytes_for_level_base决定单位是字节。各层的大小阈值会满足如下的递推关系

target_size(Lk1) target_size(Lk) * max_bytes_for_level_multiplier * max_bytes_for_level_multiplier_additional[k]

其中max_bytes_for_level_multiplier是固定的倍数因子max_bytes_for_level_multiplier_additional[k]是第k层对应的可变倍数因子。举个例子假设max_bytes_for_level_base 314572800max_bytes_for_level_multiplier 10所有max_bytes_for_level_multiplier_additional[k]都为1那么就会形成如下图所示的各层阈值。

可见这与上文讲leveled compaction时的示例是一个意思。

参数level_compaction_dynamic_level_bytes为true
这种情况比较特殊。最高一层的大小不设阈值限制亦即target_size(Ln)就是Ln层的实际大小而更低层的大小阈值会满足如下的倒推关系

target_size(Lk-1) target_size(Lk) / max_bytes_for_level_multiplier

可见max_bytes_for_level_multiplier的作用从乘法因子变成了除法因子。特别地如果出现了target_size(Lk) < max_bytes_for_level_base / max_bytes_for_level_multiplier的情况那么这一层及比它低的层就都不会再存储任何数据。

举个例子假设现在有7层包括L0L6层已经存储了276GB的数据并且max_bytes_for_level_base 1073741824max_bytes_for_level_multiplier 10那么就会形成如下图所示的各层阈值亦即L5~L1的阈值分别是27.6GB、2.76GB、0.276GB、0、0。

可见有90%的数据都落在了最高一层9%的数据落在了次高一层。由于每个run包含的key都是不重复的所以这种情况比上一种更能减少空间放大。

universal compaction

universal compaction是RocksDB中size-tiered compaction的别名专门用于L0层的compaction因为L0层的SST的key区间是几乎肯定有重合的。

前文已经说过当L0层的文件数目达到level0_file_num_compaction_trigger阈值时就会触发L0层SST合并到L1。universal compaction还会检查以下条件。

空间放大比例
假设L0层现有的SST文件为(R1, R1, R2, ..., Rn)其中R1是最新写入的SSTRn是较旧的SST。所谓空间放大比例就是指R1~Rn-1文件的总大小除以Rn的大小如果这个比值比max_size_amplification_percent / 100要大那么就会将L0层所有SST做compaction。

相邻文件大小比例
有一个参数size_ratio用于控制相邻文件大小比例的阈值。如果size(R2) / size(R1)的比值小于1 size_ratio / 100就表示R1和R2两个SST可以做compaction。接下来继续检查size(R3) / size(R1 R2)是否小于1 size_ratio / 100若仍满足就将R3也加入待compaction的SST里来。如此往复直到不再满足上述比例条件为止。

当然如果上述两个条件都没能触发compaction该策略就会线性地从R1开始合并直到L0层的文件数目小于level0_file_num_compaction_trigger阈值。

标签:
声明:无特别说明,转载请标明本文来源!