暂无图片
暂无图片
13
暂无图片
暂无图片
暂无图片

OceanBase转储

OceanBase 2022-10-15
1903

OceanBase 数据库的存储引擎基于 LSM-Tree 架构,数据大体上被分为 MemTable 和 SSTable 两部分,当 MemTable 的大小超过一定阈值时,就需要将 MemTable 中的数据转存到 SSTable 中以释放内存,我们将这一过程称之为转储。

分层转储

在 OceanBase 数据库 V2.1 版本之前,在同一时刻只会维护一个转储 SSTable,当 MemTable 需要进行转储时,会将 MemTable 中的数据和转储 SSTable 中的数据进行归并,这会带来一个问题,随着转储次数不断增多,转储 SSTable 的大小也越来越大,而一次转储需要操作的数据量也越来越多,导致转储速度越来越慢,进而导致 MemTable 内存爆。从 V2.2 版本开始,OceanBase 数据库引入了分层转储策略。

转储参考业界的部分实现,结合目前 OceanBase 数据库架构,OceanBase 数据库的分层转储方案可以理解为常见的 tiered-leveled compaction 变种方案,L0 层是 size-tiered Compaction, 内部继续根据不同场景分裂多层,L1 和 L2 层基于宏块粒度来维持 Leveled compaction。

L0 层

L0 层内部称为 Mini SSTable,根据不同转储策略需要的不同参数设置,L0 层 SSTable 可能存在可以为空。对于 L0 层提供 server 级配置参数来设置 L0 层内部分层数和每层最大 SSTable 个数,L0 层内部即分为l evel-0 到 level-n 层,每层最大容纳 SSTable 个数相同。当 L0 层 level-n 的 SSTable 到达一定数目上限或阈值后开始整体 compaction,合并成一个 SSTable 写入 level-n+1 层。当 L0 层 max level 内 SSTable 个数达到上限后,开始做 L0 层到 L1 层的整体 compaction 释放空间。在存在 L0 层的转储策略下,冻结 MemTable 直接转储在 L0-level0 写入一个新的 Mini SSTable,L0 层每个 level 内多个 SSTable 根据 base_version 有序,后续本层或跨层合并时需要保持一个原则,参与合并的所有 SSTable 的 version 必须邻接,这样新合并后的 SSTable 之间仍然能维持 version 有序,简化后续读取合并逻辑。

L0 层内部分层会延缓到 L1 的 compaction,更好的降低写放大,但同时会带来读放大,假设共 n 层,每层最多 m 个 SSTable,则最差情况 L0 层会需要持有(n X m + 2)个 SSTable,因此实际应用中层数和每层 SSTable 上限都需要控制在合理范围。

L1

L1 层内部称为 Minor SSTable,L1 层的 Minor SSTable 仍然维持 rowkey 有序,每当 L0 层 Mini SSTable 达到 compaction 阈值后,L1 层 Minor SSTable 开始参与和 L0 层的 compaction。为了尽可能提升 L1 Compaction 效率, 降低整体写放大, OceanBase 数据库内部提供写放大系数设置, 当 L0 层 Mini SSTable 总大小和 L1 Minor SSTable 大小比率达到指定阈值后, 才开始调度 L1 Compaction, 否则仍调度 L0 层内部 Compaction。

L2

L2 层是基线 Major SSTable,为保持多副本间基线数据完全一致,日常转储过程中 Major SSTable 仍保持只读,不发生实际 compaction 动作。

Queuing 表转储

在 LSM Tree 架构下,对数据行的删除并不是原地删除,而是通过写入一行 Delete 操作(tombstore)来标记删除,如果某个用户业务表主要操作为频繁的插入与删除,从绝对数据量上来看可能并不大,但是由于 LSM Tree 的架构特征,会导致对这类表的增量数据中存在大量的 Delete 标记, 即使用户的实际扫描范围很小,但是 SSTable 内部无法快速识别这些数据是否删除,仍然要扫描大量包含删除标记的数据,导致一个小查询的响应时间可能远远超过用户预期。为了解决这类表的查询性能问题,OceanBase 数据库为用户特别提供了一种支持自定义的表模式,称为 Queuing 表 (从业务角度有时候也会称为 Buffer 表 ),对其实现了特殊的转储策略。可以通过如下方式指定 queuing 表模式。

obclient> ALTER TABLE user_table table_mode = 'queuing';

对于 queuing 表具体来说,OceanBase 数据库引入一种自适应的 buffer 表转储策略,由存储层在每次转储时根据转储的统计信息来自主判断是否需要对该表采用 buffer 表转储策略,当发现一个表存在类似 buffer 表行为时,接下来会尝试对这个表做 buffer minor merge 的调度,对这个表基于 Major SSTable 和最新的增量数据以当前的读快照时间生成一个 Buf Minor SSTable,这次 Compaction 动作会消除掉增量数据里的所有 Delete 标记,后续查询基于新生成的 Buf Minor SSTable 就可以避免原有的大量无效扫描动作。

buffer

转储触发

转储有两种触发方式:自动触发与手动触发。

当一个租户的 MemTable 内存的使用量达到 memstore_limit_percentage * freeze_trigger_percentage 所限制使用的值时,就会自动触发冻结(转储的前置动作),然后系统内部再调度转储。

您也可以通过以下的运维命令手动触发转储。

说明

memstore_limit_percentage 用于设置租户使用 memstore 的内存占其总可用内存的百分比。有关该配置项的详细介绍,参见《参考指南》文档中的 集群级配置项 章节。

ALTER SYSTEM MINOR FREEZE [zone] | [server_list] | [tenant_list] | [replica]
 
tenant_list:
    TENANT [=] (tenant_name_list)
 
tenant_name_list:
    tenant_name [, tenant_name ...]
 
replica:
    PARTITION_ID [=] 'partition_idx%partition_count@table_id'
 
server_list:
    SERVER [=] ip_port_list

示例:

  • 集群级别转储
obclient> ALTER SYSTEM MINOR FREEZE;
  • Server 级别转储
obclient> ALTER SYSTEM MINOR FREEZE SERVER='10.10.10.1:2882';
  • 租户级别转储
obclient> ALTER SYSTEM MINOR FREEZE TENANT='prod_tenant';
  • Replica 级别转储
obclient> ALTER SYSTEM MINOR FREEZE PARTITION_ID = '8%1@1099511627933';

需要注意的是,尽管允许只针对单个分区手动触发 Minor Freeze,但由于多个不同的分区可能共用相同的内存块,因此对单个分区的 Minor Freeze 可能并不能有效地释放内存,而针对租户的 Minor Freeze 可以有效地释放对应租户 MEMTable 的内存。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论