前言
上一篇文章[Apache Doris 技术实现 - 冷热数据存储(一)]主要讲述了冷热数据存储与存算分离之间的关系,结合数据仓库的历史,分析了存算分离在实时数仓上面的局限性,相比起分布式计算类项目(spark、flink),实时数仓只能做到有限制的存算分离。并根据这一现状,描述了一个冷热数据与存算分离结合的模型。接下来,我会先后讲述该模型的几个主要模块的原理与实现:热数据转冷、冷数据读写。
热数据转冷
热数据转冷是冷热数据存储重要的一步,所有冷热数据的相关操作都以此为开始,当数据转为冷数据后,将会有冷热数据同步等多方面的问题需要考虑。
冷热数据转换规则StoragePolicy
StoragePolicy由FE的PolicyMgr进行管理,用来配置冷热数据的转换规则。该信息会随着心跳同步给每一个BE(refreshStoragePolicy()),BE将以此作为数据进行冷热数据转换的依据。
根据用户的使用习惯,以及数据的业务特性,冷热数据转换规则可分为两类:
**第一类:**明确指定冷却时间点:有些数据拥有时间特性,前一年的数据在后一年就已经失去了时效性,这种数据通过指定具体的时间来界定其转为冷数据的时间。
CREATE STORAGE POLICY testPolicy
PROPERTIES(
“storage_resource” = “s3”,指定冷数据存储使用的资源名称,见SHOW RESOURCE
“cooldown_datetime” = “2022-06-02 00:00:00”,//指定热数据转为冷数据的时间。
);
**第二类:**根据活跃时间指定数据冷却时间:有些数据有着固定的活跃时间,比如用户行为数据,每月生成的用户行为数据在当月是使用最频繁的,而随着时间的推移,这些数据的重要性逐步降低,最终转为不活跃数据。这种情况下可以对数据指定活跃时间,当数据活跃时间结束后,该数据转为冷数据。
CREATE STORAGE POLICY testPolicy2
PROPERTIES(
“storage_resource” = “s3”,
“cooldown_ttl” = “1d”//指定数据活跃时间,超过这一时间,热数据将转为冷数据。
);
TABLE的冷热数据配置
冷热数据的调度流程,是从TABLE的冷热数据配置信息开始。在建表时指定所要使用的冷热数据规则名(storage_policy),映射为StoragePolicy。
CREATE TABLE (
……
) PROPERTIES (
“storage_policy” = “storage_policy_name1”
);
上面的配置,可以为整个表指定冷热数据规则,而大多数情况下,我们的数据是拆分成多个PARTITION的,每个PARTITION所需要的冷热数据规则有可能是不同的,这时就需要针对PARTITION来进行配置:
ALTER TABLE TblPxy01 ADD PARTITION
p2 VALUES [(“10000”), (“20000”))
(“remote_storage_policy” = “testPolicy”);
配置中的storage_policy信息存放在PARTITION的每个TABLET中,当创建及修改TABLET时,storage_policy信息随着TABLET下发给BE,由BE来判断该TABLET何时可以开始进行冷热数据转换。
冷热数据转换守护进程(cooldown_tasks_producer_thread)
如下图所示,cooldown_tasks_producer_thread是BE的一条守护进程,其对本BE的所有存活的TABLET进行遍历,检查每个TABLET的配置信息。当发现该TABLET配置了storage_policy,说明需要对其进行冷热数据转换。
根据storage_policy中的配置,BE将从缓存信息中的StoragePolicy列表中获取对应的规则信息,然后根据这个规则,判断当前tablet是否需要进行冷热数据转换,将数据存放于远程存储集群上(如S3)。
冷数据读写
冷热数据模型下的存储结构
正如前一篇文章所说的,DORIS的存算分离,是基于冷热数据模型的存算分离。这种情况下,数据的存储结构与原本的线本地存储结构有着巨大的不同。
了解过DORIS的代码结构的朋友应该都知道,BE在存储TABLET数据的时候,TABLET下面还会有ROWSET和SEGMENT的划分。其中ROWSET代表着数据导入批次,同一个ROWSET一般代表着一个批次的导入任务,比如一次stream load,一个begin/commit事务等,都对应一个ROWSET,ROWSET的这种特性,意味着其具有着事务的特点,即是说,同一个rowset可以作为一个独立的数据单元存在,其中的数据要么全部有效,要么全部无效。
正因为如此,以rowset为基本单元对数据进行冷热转换,可以更容易的解决冷热数据迁移过程中有新数据写入的问题。
如下图所示,对于进入冷热数据转换状态的TABLET,其ROWSET被分成两部分。
一部分在本地,这部分数据往往是新写入的数据,还未触发上传操作。
另一部分在远程存储集群(S3/HDFS),这部分数据相对较早,是在此前已经触发上传到了存储集群上的数据。
冷数据读取
当冷数据需要读取的时候,由于数据已经被拆分成了两部分,需要从本地和远程存储集群(S3/HDFS)上分别读取数据。
如下图所示,本地文件和远程文件的读取被封装成了一个FileReader的虚基类,实现两个派生类LocalFileReader和S3FileReader,分别对应本地文件读取与S3文件读取。当有读取请求到达TABLET时,TABLET会根据条件找到对应的ROWSET,这些ROWSET有些是本地存储,有些是远程存储(S3)。通过映射关系,ROWSET找到各自的FileReader,完成数据读取,合并后即是完整的TABLET数据。
在这里,远程数据文件为了保证读取效率,可以有多种优化的方向,比如加一层本地缓存,比如使用本地索引等。这些在后续文章中详细说明。
冷数据写入
与冷数据读取相似,冷数据写入也封装了一个FileWriter虚基类,如下图所示:
新写入的数据会在TABLET的本地存储部分新增一个ROWSET,这与普通的TABLET相同,也保证了冷数据也可写入的特性。而这部分写入到本地的数据在某个时间点会与远程的冷数据进行合并,并上传到远程存储集群。这一步骤则是由前文提到的守护进程cooldown_tasks_producer_thread来完成的。
总结
本文介绍了DORIS冷热数据转换的基本功能,热数据转冷与冷数据读写。关于冷热数据的实现,还有很多方面可讲。比如冷数据的文件合并(COMPACTION)、冷数据的表结构修改(SCHEMA_CHANGE)、冷热数据由多副本转单副本等,请期待后续的技术分享。
- 作者介绍 -
彭翔宇
百度 PALO 团队资深研发工程师,丰富的大数据工程研发经验,Apache Doris 冷热存储模块主要实现者,擅长 Doris 生态化组件研发。
相关阅读
Apache Doris 技术实现 - 冷热数据存储(一)
Apache Doris 开源社区链接参考
https://github.com/apache/doris