通过上一篇博客,我相信大家都能理解,在LSM-Tree中,compact是平衡读/写/空间放大三者的一个关键流程。今天我们就一起来看看OcenaBase里到底有哪些compact过程。
不知道大家有没有查看过ob_compaction_util.h源码文件,这里我们把文件里的ObMergeType
枚举值拎出来,去掉一些无关的类型,可以看到有一系列M开头的Merge类型:
enum ObMergeType
{
MINOR_MERGE = 0,
...
META_MAJOR_MERGE = 2,
MINI_MERGE = 3,
MAJOR_MERGE = 4,
MEDIUM_MERGE = 5,
...
};
这些就是OceanBase里主要的几种compact过程,我们可以把他们称作“M系列”的Merge。
暂停30秒,对比官网的这张图,大家能否找到以上几种Merge所对应的行为呢?
时间到了,让我来为大家揭秘吧~
图中Frozen MemTable下刷到Mini SStable的过程,对应的是MINI_MERGE,也就是OceanBase中俗称的“转储”。转储会选取一至多个Frozen MemTable,将他们合成一个Mini SSTable,这对于内存空间的释放有着重要作用。
为了最大程度地缓解读放大与空间放大,OceanBase会定时自动触发MAJOR_MERGE,也就是OceanBase中俗称的“合并”。简单起见,我们姑且认为合并会将所有Mini SStable (Minor SStable),和旧的Major SStable共同合成一个新的Major SSTable,这个过程相当于产生了一个新的快照。在还没有数据的时候,依然会存在一个Major SSTable,只不过SStable内是没有数据的。
容易想象的是,如果在两次合并之间不对Mini SSTable做其他compact操作的话,一方面SSTable数量会不受控制,另一方面合并的开销可能会非常大。
因此OceanBase会自动触发MINOR_MERGE,也就是涉及到Mini SSTable或者Minor SSTable的compact过程。让我们思考一下,在没有数据的情况下,Minor SSTable是否存在呢?很显然,答案是否定的。不同于Major SSTable,Minor SSTable主要起到一个维持SSTable数量的中间作用,是允许没有的。事实上,Mini SSTable和Minor SSTable的主要区别在于数据量的多少。假设在还没有Minor SSTable的时候,多个Mini SSTable会执行MINOR_MERGE并合成一个可能更大的SSTable,如果这个SSTable足够大,那么我们可以从逻辑上认为它是一个Minor SSTable,反之,我们可以认为它依然是个Mini SSTable。也就是说,在真正执行MINOR_MERGE时,如果选中的多个Mini SSTable数据量与当前的Minor SSTable数据量悬殊过大时,我们认为此次compact过程加入Minor SSTable并没有很好的收益,反而徒增写放大,因此会选择只将多个Mini SSTable合成一个更大的Mini SSTable。
至此,图中显而易见的行为与Merge类型的对应关系就介绍完了,接着我们来看看META_MAJOR_MERGE和MEDIUM_MERGE分别代表着怎样的compact过程。
在这之前,我们需要从集群层面来重新认识一下OcenaBase。大家都知道OceanBase是一个分布式数据库,对于一个OceanBase集群来说,整个集群的存储架构如下图所示。
在一个 OceanBase 集群内,每个节点上会运行一个叫做OBServer的服务进程。每个集群可以创建很多个互相之间隔离的数据库"实例",这样一个实例被叫做一个租户。每个租户可以拥有多份数据副本,每份数据都会被维护在一个OBServer上。更细粒度地,每份数据可能来自多个表,每一个表的数据可以按照某种划分规则水平拆分为多个分片,每个分片被叫做一个表分区,每个物理意义上的表分区都有一个用于存储数据的存储层对象,被叫做 tablet。在上图中,每个租户具有三个副本,每个副本都包含多个tablet。
我们常说的合并,实际上是对某个租户产生一个全局快照,也就是“租户级合并”,这需要租户内所有的分区,以及分区的所有副本都执行生成新Major SSTable的compact过程。
既然合并是以租户为单位的,那么我们很自然的可以想到,为什么不能以更小的粒度来减少一次合并的开销呢?MEDIUM_MERGE 就起到了这个作用。和MAJOR_MERGE不同,MEDIUM_MERGE 只会让某一个分区的所有副本执行将所有Mini SStable (Minor SStable),和旧Major SStable共同合成一个新Major SSTable的compact过程,我们可以把他称为“分区级合并”。
更进一步地,META_MAJOR_MERGE只需要在某个分区的某个副本内,执行一次将所有Mini SStable (Minor SStable),和旧Major SStable共同合成一个新Meta Major SSTable(这里的Meta Major SSTable和Major SSTable类似,但是是可以和Major SSTable共同存在的SSTable,不需要保证多副本的一致)的compact过程,这个特殊的过程能够在加速查询的同时极大地减少整理数据的开销。
到这里,想必大家对于几种OceanBase内的compact过程已经有了基本的认识,至于其中更多的细节我们会通过更多的章节来展开介绍。有什么问题,或者想更多的了解哪方面的内容,大家都可以在博客下方留言。在这里也鼓励大家到GitHub上看看源码,转储合并的大量源码都集中在compaction目录内。