StarRocks 存算分离数据回收原理

news2024/11/25 10:38:42

前言

StarRocks存算分离表中,垃圾回收是为了删除那些无用的历史版本数据,从而节约存储空间。考虑到对象存储按照存储容量收费,因此,节约存储空间对于降本增效尤为必要。

在系统运行过程中,有以下几种情况可能会需要删除对象存储上的数据:

  1. 用户手动执行了删除库、表、分区等命令,如执行了 drop table、drop database 以及 drop partition 等命令
  2. 随着系统内 Compaction 任务不断进行,合并之前的数据文件可以被安全回收

目前在 StarRocks 的存算分离表存储在对象存储上的文件类型包含如下几种:

  1. Segment 文件:导入过程中会产生数据文件,存算分离的数据文件格式与存算一体保持一致
  2. Txn Log 文件:StarRocks 存算分离实现中,每次导入或者 Compaction 都会产生一次事务,每个 Tablet 在数据写入的最后阶段都会产生一个 Txn Log 文件,记录本次导入新增的数据文件列表
  3. Tablet Meta 文件:StarRocks 每次导入或者 Compaction 都会产生全局唯一的版本。而 Tablet Meta 文件在事务提交阶段产生,存储 Tablet 特定版本的元数据信息,其中主要记录了该版本所有可见的数据文件名

本文旨在描述 StarRocks 存算分离表垃圾回收的原理,会针对上述两种数据清理场景分别描述其内部原理,帮助开发和运维人员能更好地理解并根据实际需要做出合适的配置,以在性能和成本方面取得平衡。


数据多版本技术

在介绍数据清理之前,我们有必要先介绍下目前 StarRocks 存算分离的数据多版本技术,以便更好地理解垃圾数据回收原理。

StarRocks 存算分离版本中,数据在对象存储上的组织结构如下图所示:

d746aa5340bf59d3ba37d19544369c08.jpeg

上图中共产生了三次数据导入事务,其中:

  • Load Txn 1: 在事务数据写入阶段,生成了新数据文件 file 1 & file 2,该事务提交后生成了 Tablet Meta V1,其中记录该版本可见的文件列表为 {file-1, file-2}
  • Load Txn 2: 在事务数据写入阶段,生成了新数据文件 file 3 & file 4。在提交时,根据前一个版本(即 Tablet Meta V1)然后加上本次导入事务生成的新数据文件(file-3 & file-4),生成了新的 Tablet Meta V2,因此,该版本可见的文件列表为 {file-1, file-2, file-3, file-4}
  • Load Txn 3: 在事务写入阶段,产生了新数据文件 file 5。该事务提交时,根据前一个版本(即 Tablet Meta V2)然后加上本次导入事务生成的新数据文件(file-5),产生了新的 Tablet Meta V3,因此,该版本的可见文件列表为 {file-1, file-2, file-3, file-4, file-5}


除了用户导入事务产生了新的数据版本,在存算分离架构中,系统后台 Compaction 任务也会产生新数据版本。Compaction 的目的有二: 1). 将多个版本的小文件合并为大文件,减少查询时的随机 IO 次数,2). 消除重复数据记录,减少数据总量。

在存算分离表中,每次 Compaction 同样会产生一个全新的版本。依然以上面为例,假如在上面 Txn 3 之后新的事务 Txn 4 为一次 Compaction 任务,并且将 file1 ~ file4 这4个文件合并成为 file-6,那么该事务提交时,生成的新版本 Tablet Meta V4 内记录的文件列表为 {file-5, file-6}。

fe82a95b5362ac9685b979d089bb0899.jpeg

观察上例并思考可知,如果系统在运行过程中一直不会进行 Compaction。那么系统中的数据文永远也无法被删除。试想上例中我们即使将 Tablet Meta V1,Tablet Meta V2 文件删除,但我们无法删除 file-1、file-2、file-3 以及 file-4,因为这些文件依然被 Tablet Meta V3 所引用。

但有了数据合并(Compaction)后,情况就变得不一样了。上例中,由于发生了一次 Compaction(上图中的 Txn 4),将 file-1、file-2、file-3、file-4 合并生成了新文件 file-6 并生成了新的 Tablet Meta V4,由于 file-1 至 file-4 中的内容已经在 file-6 中存在,因而,一旦版本 V1、V2、V3 不再被访问,file-1、file-2、file-3、file-4 便可以被安全删除。此时的数据版本情况如下图所示:

21686f5996717f45d8c1b222b58bfa44.jpeg

因此,综合上面的讨论,我们可以发现,只有在 Compaction 完成后原始的数据文件方可被删除(但 Tablet Meta 文件的清理依赖其他规则)。

目前我们在 Tablet Meta 组织上采用了一种高效方法:

对于 Compaction 事务, 我们会在其产生的 Tablet Meta 中记录本次合并任务的输入文件列表,这样,下次我们在清理该 Tablet Meta 时即可安全删除这些输入文件。

仍然以上面为例,Compaction Txn 4 在生成的 Tablet Meta V4 中记录了本次合并任务的输入文件 file-1、file-2、file-3、file-4。这样,下次系统清理掉 Tablet Meta V4 之后,拿到这个文件列表,便可以安全删除。

但这种删除方式也依赖一个前提:即 Tablet Meta 按照版本顺序删除,不可乱序。试想一下,上面的例子中,我们在删除版本 V4 时必须确保 V3 已经被安全删除。否则,访问 V3 时就会发现 file-1 这些已经被删除了。


工程实现

本章节主要描述当前垃圾数据清理的工程实现原理。


FE 后台清理线程

当前存算分离表的垃圾回收任务以 Partition 为单位执行,由 FE 节点构建清理任务并交由 CN 节点执行。具体来说,FE 会同时为若干个活跃 Partition 创建 Vacuum 任务,然后下发至 CN 执行。
Leader FE 节点上存在后台 Vacuum 线程,周期性运行,每次运行时:

1. 筛选出当前需要执行 Vacuum 的 Partition
2. 为筛选出的 Partition 构造 Vacuum 任务,交由 FE 端线程池处理这些任务
3. FE 端线程池可同时执行若干任务(由参数控制),每个任务都会下发给 Partition 内 Tablet 所在的 BE 执行


在步骤 2 中构造的 Vacuum 任务中,最关键的参数有三:

minRetainVersion: 控制 CN 端执行时需要保留的最小版本号。FE 决定了某个分区可以最多保留多少个历史版本。避免 CN 执行时清理过猛,将历史版本清理过多,造成正在进行中的查询访问历史版本数据失败。
graceTimestamp: 控制多长时间内产生的 Tablet Meta 不会被清理,避免在高频导入场景下,刚刚产生的 Tablet Meta 被立即回收
minActiveTxnId: 用于回收 Txn Log 文件


FE 为需要 Vacuum 的 Partition 构造好 VacuumRequest 发往 CN 节点,接下来 CN 节点只需要负责执行任务即可


CN 执行垃圾回收

CN 只需要负责执行 FE 下发的 VacuumRequest 即可。目前 Vacuum 任务复用了 RELEASE_SNAPSHOT 线程池(该线程池在存算分离集群上无用,因而可直接复用)。由于该线程池工作线程数量较少(默认为5),这可能在一定程度上影响清理速度,需要特别注意。


清理 Tablet Meta 文件

清理 Tablet Meta 实际上主要是清理如下内容:

  1. Tablet Meta 文件(即从对象存储上删除特定版本的 Tablet Meta 文件)
  2. 如果该版本是由 Compaction 事务产生,便可以收集到 Compaction 所对应的输入 Segment 文件,以便接下来删除(参考上面的例子,删除 Tablet Meta V4 的时候可以获取可以删除的数据文件 file-1 ~ file-4)

这里需要特别说明的一点是,对于某个特定 Tablet 的 Meta 文件的清理是往前回溯进行的。具体来说,FE 的 VacuumRequest 中记录了最大可回收版本号(min_retain_version),CN 节点处理时就从该版本开始逐步向前回溯。

例如下例中,假如最新的版本为 v10,且系统配置保留最近的3个版本,那么 min_retain_version 便是 v8,按照规则就是从 v7 开始向前回溯直到 v1。另外,在回溯时我们还会获取 Meta 文件的最后创建时间,如果没有超过一个特定的间隔(grace_timestamp),那也暂时不回收该 Tablet Meta 文件。

9fa739b02d92d1f0b4fb180d344c5893.jpeg

之所以采用这种前向回溯的方式的原因在于:

  1. 避免 list 所有 Meta 文件,因为 list object 调用在对象存储上效率非常低下
  2. 避免从前往后扫描时需要不断获取 Tablet 每个 Meta 文件的内容以获得 Compaction Input(假如 Meta 文件出现 cache miss,就会产生一次对象存储访问,效率低下)

不妨举个例子说明,如下图所示:

6621e893846908ea40f761f6a485f138.jpeg


当前系统中有 4 次事务,其中

  1. Load Txn 1:导入事务,产生数据文件 file-1、file-2,该事务生成的 Meta V1 内记录文件为 {file-1, file-2}
  2. Compaction Txn 2:Compaction 事务,将 file-1、file-2 合并为新文件 file-3,该事务生成的 Meta V2 内记录文件为 {file-3},同时记录了 Compaction Inputs 为 {file-1, file-2}
  3. Load Txn 3:导入事务,产生数据文件 file-4,该事务生成的 Meta V3 内记录文件为 {file-3, file-4}
  4. Compaction Txn 4:数据合并事务,将 file-3、file-4 合并为新文件 file-5,该事务生成的 Meta V4 内记录文件为 {file-5}, 同时记录了 Compaction Inputs 为 {file-3, file-4}

试想下,如果按照顺序遍历的方式清理,那么我们首先:

  1. 要通过 list object 获取起始版本号,为 V1,产生一次对象存储的 list object 调用
  2. 以 V1 为起始版本号,逐个递增开始获得 Meta 文件,且对于每个 Meta 文件都需要读取内容,获得 Compaction Input Files 字段,取得可以被清理的数据文件列表,那么本例中就需要执行 4 次,如下:
打开并读取 Tablet Meta V1,获取 Compaction Input Files,然后清理
打开并读取 Tablet Meta V2,获取 Compaction Input Files,然后清理
打开并读取 Tablet Meta V3,获取 Compaction Input Files,然后清理
打开并读取 Tablet Meta V4,获取 Compaction Input Files,然后清理

这里需要访问 V1 ~ V4 这所有 Tablet Meta,而获取 Tablet Meta 文件内容可能是一个较为耗时的动作(假如 Tablet Meta Cache Miss 时就需要访问对象存储)。

而通过从后往前的回溯遍历方式就可以避免上述问题,但前提是需要构建好一个前向回溯链。

为了构造前向回溯链,我们做了一个优化,在每个 Tablet Meta 中记录了前一次 Compaction Txn 的版本号(prev_garbage_version),例如在本例中,Tablet Meta V3 中记录了该字段为 V2,而 Tablet Meta V4 由于拷贝自 Tablet Meta V3,因此 prev_garbage_version 字段值便也为 V2。

a205a0c47e819398dfab4928baa6a243.jpeg

回收时,首先获得 Tablet Meta V4,假如判断其为安全可删除的,接下来找到 prev_garbage_version,这里记录为 V2,因而,这里便可以跳过 Tablet Meta V3,直接找到 Tablet Meta V2,获得其 Compaction inputs,也可以被安全删除。而由于 Tablet Meta V2 内的 prev_prev_garbage_version 为空,因此,便不再需要往前回溯了。这样,就避免了打开 Tablet Meta V1 和 Tablet Meta V3,就获得了所有 Compaction 事务的 Input Files。


清理 Segment 文件

垃圾回收的核心在于回收无用数据文件,而根据上文的基本原理可知,删除数据文件一般发生在清理那些 Compaction 事务产生的 Tablet Meta 文件时,这些文件中记录了当次 Compaction 的输入文件列表,由于这些文件已经被成功合并生成了新的文件,因此,这些原始输入文件可以被安全删除了。

因此,对于 CN 节点来说,就非常简单了,在上面的清理 Tablet Meta 文件时,捎带获取到 Tablet Meta 文件中记录的 Compaction Input Files 内容,然后就可以安全删除。

考虑到一般对象存储提供了批量删除文件接口,CN 在清理 Segment 文件时也进行了批量删除,由参数 lake_vacuum_min_batch_delete_size 控制批次大小。


清理 Txn Log 文件

Txn Log 文件在数据导入过程中产生,记录本次导入或者 Compaction 过程中产生的新文件。正常情况下,Txn Log文件一般在事务提交后即被删除。但异常时该文件可能会残留,也依赖后台的 Vacuum 任务来统一清理。

CN 清理时首先通过 list objects 来获得当前所有的 Txn Log 文件(由于 Txn Log 文件存储在单独 log/ 目录下,对象数较少,list 效率一般不会成为大问题),然后从文件名中解析出 tablet id 和 txn id 信息,接下来判断该 Txn Log 文件是否可以被安全删除,原理也比较简单:

判断该txn id是否比当前系统中的最小活跃事务id更小(min active txn id),如果是,那么意味着该事务一定在 FE 上已经结束了(要么已提交,要么已回滚),此时 Txn Log 即可被安全删除。


删除表和分区

StarRocks 目前有如下几种方式来删除表和分区:

drop table xxx; 

drop table xxx force; 

drop partition xxx; 

drop partition xxx force;

前者实现了回收站机制,删除的表会先放入回收站,直到一段时间后才开始真正删除。而后者则立即删除,无任何缓冲时间。

当前实现中,删除表会触发我们物理删除表上的所有数据,而从对象存储删除数据是一个非常耗时的动作。我们将两种删除模式进行统一,都统一为后台异步清理模式。用户提交的删除表命令会立即返回成功,后台线程会慢慢删除表的物理数据。


删除表

删除分区的实现原理同删除表基本一致,也都是将待删除的分区加入回收站中,而 FE 后台线程则会不断地从回收站中取出需要被删除的 table,执行真正的删除动作。

真正的数据删除在 deleteFromRecycleBin 内实现,对于存算分离内表,对于一个表进行物理删除时,内部也是按照分区为单位逐个进行删除,因为我们当前最新的版本是按照分区为粒度组织数据目录,如下所示:

${cluster_uuid}/${db_id}/${table_id}/${partition_id}

而删除最终是调用了 CN 节点的 drop_table 的 RPC 接口来执行真正的数据删除。

真正删除时,通过调用 remove_all 来直接将分区目录下面的所有文件一次性删除,效率较高。而且,可以发现,这里的删除任务会被提交到一个独立的线程池来执行。


删除分区

删除分区的实现原理同删除表基本一致,也都是将待删除的分区加入回收站中,然后在回收站后台慢慢清理。最终的清理也是调用 CN 节点的 drop_table 的 rpc 接口来完成真正的数据删除。这个已经在前面描述过,这里就不再赘述。


缓存清理

当前的实现中,回收对象存储的垃圾数据文件时并不会同步删除缓存,缓存淘汰依赖自身的 LRU 机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2061428.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

详解华为项目管理,附华为高级项目管理内训材料

(一)华为在项目管理中通过有效的沟通、灵活的组织结构、坚持不懈的努力、细致的管理和科学的考核体系,实现了持续的创新和发展。通过引进先进的管理模式,强调以客户需求为导向,华为不仅优化了技术管理和项目研发流程&a…

el-table自定义样式,表头固定,数据过多时滚动

最终效果&#xff1a;&#xff08;此处没体现出来滚动&#xff0c;数据没那么多&#xff09; 1.表头固定&#xff0c;设置表头样式&#xff0c;修改表格背景色 <div class"category-table"> <el-table ref"tableRef" class"common-table&quo…

java之类和对象的介绍

1.面向对象和面向过程的概念&#xff1a; 面向对象&#xff1a;面向对象是解决问题的一种思想&#xff0c;主要依靠对象之间的交互完成一件事。 面向过程&#xff1a;注重完成一件事情的过程&#xff0c;后续代码维护扩展较为麻烦。 以洗衣服为例&#xff0c;面向对象为传统…

微软AI人工智能认证有哪些?

微软提供的人工智能认证主要包括以下几个方面&#xff1a; Azure AI Fundamentals&#xff08;AI900认证&#xff09;&#xff1a;这是一个基础认证&#xff0c;旨在展示与Microsoft Azure软件和服务开发相关的基本AI概念&#xff0c;以创建AI解决方案。它面向具有技术和非技术…

C++学习路线分享

我上大学学的第一门编程语言便是C&#xff0c;靠着那本饱受诟病的谭浩强版的教材度过了大一上学期。学的内容现在看来相当之浅&#xff0c;如果没记错的话只学了个基本的语法&#xff0c;考试的时候考一些冒泡&#xff0c;快排之类的东西就结束了。感觉那些有计算机教育背景的学…

解决Qt多线程中fromRawData函数生成的QByteArray数据不一致问题

解决Qt多线程中fromRawData函数生成的QByteArray数据不一致问题 目录 &#x1f514; 问题背景&#x1f4c4; 问题代码❓ 问题描述&#x1fa7a; 问题分析✔ 解决方案 &#x1f514; 问题背景 在开发一个使用Qt框架的多线程应用程序时&#xff0c;我们遇到了一个棘手的问题&…

【Linux】生产消费模型实践 --- 基于信号量的环形队列

你送出去的每颗糖都去了该去的地方&#xff0c; 其实地球是圆的&#xff0c; 你做的好事终会回到你身上。 --- 何炅 --- 基于信号量的环形队列 1 信号量2 框架构建3 代码实现4 测试运行 1 信号量 信号量本质是一个计数器&#xff0c;可以在初始化时对设置资源数量&#xf…

数据结构——链式队列和循环队列

目录 引言 队列的定义 队列的分类 1.单链表实现 2.数组实现 队列的功能 队列的声明 1.链式队列 2.循环队列 队列的功能实现 1.队列初始化 (1)链式队列 (2)循环队列 (3)复杂度分析 2.判断队列是否为空 (1)链式队列 (2)循环队列 (3)复杂度分析 3.判断队列是否…

91. UE5 RPG 实现拖拽装配技能以及解除委托的绑定

在上一篇文章里&#xff0c;实现了通过选中技能&#xff0c;然后点击下方的装备技能插槽实现了技能的装配。为了丰富技能装配功能&#xff0c;在这一篇里&#xff0c;我们实现一下通过拖拽技能&#xff0c;实现拖拽功能&#xff0c;我们需要修改两个用户控件&#xff0c;一个就…

鸿蒙内核源码分析(信号生产篇) | 注意结构体的名字和作用.

信号生产 关于信号篇&#xff0c;本只想写一篇&#xff0c;但发现把它想简单了&#xff0c;内容不多&#xff0c;难度极大.整理了好长时间&#xff0c;理解了为何<<深入理解linux内核>>要单独为它开一章&#xff0c;原因有二 信号相关的结构体多&#xff0c;而且…

RTC碰到LXTAL低频晶振停振怎么办?

GD32F303的RTC模块框图如下图所示&#xff0c;RTC时钟源可选择HXTAL/128、LXTAL或IRC40K&#xff0c;一般为了实现更精准的RTC时间&#xff0c;MCU系统均会外挂32.768KHz LXTAL低频晶振&#xff0c;但由于低频晶振负阻抗较大&#xff0c;不容易起振&#xff0c;若外部电路布线、…

vue3 antdv3 去掉Modal的阴影背景,将圆角边框改为直角的显示,看上去不要那么的立体的样式处理。

1、来个没有处理的效果图&#xff1a; 这个有立体的效果&#xff0c;有阴影的效果。 2、要处理一下样式&#xff0c;让这个阴影的效果去掉&#xff1a; 图片的效果不太明显&#xff0c;但是阴影效果确实没有了。 3、代码&#xff1a; /* 去掉遮罩层阴影 */.ant-modal-mask {…

Maven命令传pom或者jar异常

上传命令&#xff1a;mvn deploy:deploy-file -Durlhttp://****&#xff1a;****/repository/chntdrools7741-releases -DrepositoryId**** -DfileD:/tempRepo/org/kie/kie-api-parent/7.69.0.Final/kie-api-parent-7.69.0.Final.pom -DpomFileD:/tempRepo/org/kie/kie-api-par…

三级_网络技术_39_综合题(命令)

一、 如下图所示&#xff0c;某校园网用10Gbps 的POS技术与Internet相连&#xff0c;POS接网的幅格式早SDH。路由协议的选择方案是校园网内部采用OSPF协议&#xff0c;校园网与lntemnet的连接使用静态路由协议。校园网内的路由器R1设为DHCP服务器&#xff0c;可分配的IP地址是…

【22-54】创建者模式(详解五大模式)

目录 一.创建者模式介绍 二.单例设计模式 2.1 单例模式的结构 2.2 单例模式的实现 2.2.1.1 饿汉式-方式1&#xff08;静态变量方式&#xff09; 2.2.1.2 饿汉式-方式2&#xff08;静态代码块方式&#xff09; 2.2.2.1 懒汉式-方式1&#xff08;线程不安全&#xff09; 2…

用手机写一本电子书

第1步、进入Andi.cn网站 第2步、点击登录&#xff0c;注册用户 第3步、点击去创作&#xff0c;进入创作页面 第4步、点击右下角的小笔&#xff0c;写一篇文章 第5步、下翻&#xff0c;点击提交按钮 第6步、再写一篇文章 第7步、点击栏目设计 第8步、进入栏目设计&#xff0c;点…

excel卓越之道笔记

excel快捷键 1.Alt+=一键求和 2.Tab补全函数名称 3.CONCAT可以连选,CONCATENATE只能一个单元格一个单元格点选 4.excel365用不了phonetic函数,但是可以用concat代替 5.textjoin连接标识码,在Arcgis中筛选出所需要素,也是很好用的 6.法1:alt+; 定位可见单元格,复制后只…

Linux入门——01常用命令

0.命令行解释器shell 用户无法直接给操作系统指令&#xff0c;需要经过shell,才能让操作系统明白。如果用户对操作系统非法操作&#xff0c;会有shell保护。shell本身也是一个进程&#xff0c;当然&#xff0c;用户给shell的指令&#xff0c;shell会派生出子进程进行执行&#…

Unity Protobuf3.21.12 GC 问题(反序列化)

背景&#xff1a;Unity接入的是 Google Protobuf 3.21.12 版本&#xff0c;排查下来反序列化过程中的一些GC点&#xff0c;处理了几个严重的&#xff0c;网上也有一些分析&#xff0c;这里就不一一展开&#xff0c;默认读者已经略知一二了。 如果下面有任何问题请评论区留言提…

【Kubernetes中如何对etcd进行备份和还原】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…