Halodoc数据工程已经从传统的DataPlatform10发展到使用LakeHouse架构的现代DataPlatform20转型。在之前的博客中,我们提到了Halodoc如何实现Lakehouse架构来处理大规模分析工作负载。它提到了构建Platform20时的设计考虑因素、实践和经验教训。在本博客中,我们将仔细研究ApacheHudi以及它如何帮助您构建事务数据湖。我还将重点介绍我们在构建Lakehouse时面临的一些挑战以及我们如何使用ApacheHudi克服这些挑战。
阿帕奇连帽衫
让我们从对ApacheHudi的基本了解开始。Hudi是一个丰富的,用于在自我管理的数据库层上构建具有增量数据管道的流数据湖,并针对湖引擎和一般批处理进行了优化。ApacheHudi将核心仓库和数据库功能直接引入您的数据湖。Hudi提供表、事务、高效上传/删除、高级索引、流式摄取服务、数据集群/压缩优化和并发性,同时将数据保持为开源文件格式。ApacheHudi可以轻松地在任何云存储上使用。ApacheHudi的高级性能优化使分析工作负载能够使用流行的查询引擎更快地运行。让我们看一下我们在构建Lakehouse时面临的一些关键挑战,以及我们如何使用Hudi和AWS云服务解决这些挑战。
在LakeHouse中执行增量更新
每个人在构建事务数据湖时面临的主要挑战之一是确定用于更新数据湖中记录的正确主键。主键最常用作唯一标识符和时间戳字段,以过滤掉传入批次中的重复记录。在Halodoc中,大多数微服务使用RDSMySQL作为数据存储。我们有超过50个MySQL数据库需要迁移到数据湖,其中事务会经历各种状态,并且大多数情况下更新会频繁发生。
题MySQLRDS以秒格式存储时间戳字段,导致难以跟踪以毫秒或微秒为单位发生的事务。使用业务修改时间戳字段来识别传入批次中的最新事务对我们来说是有题的。挑战。我们尝试了多种方法来解决这个题,包括使用排名函数、组合多个字段以及选择正确的组合键。复合键选择在表之间并不统一,并且可能需要不同的逻辑来识别最近的事务。
解决方案AWSDataMigrationService可以配置转换规则,允许您添加具有自定义或预定义属性的其他标头。
ar_h_change_seq来自源数据库的唯一增量号,由时间戳和自动增量号组成。该值取决于源数据库系统。
标头可让您轻松过滤掉重复记录并更新数据湖中的最新记录。标题仅适用于正在进行的更改。完全加载默认分配记录0,而增量记录则为每条记录添加唯一标识符。在prejoin字段上配置ar_h_change_seq以从传入批次中删除重复记录。
连帽衫包括
预组合=ar_h_change_seqhoodiedatasourcewriteprecombinefield:预组合hoodiedatasourcewritepayloadclass:'orgapachehudicommonmodelDefaultHoodieRecordPayload'hoodiepayloadorderingfield:预组合
数据湖中的小文件题
构建数据湖时,更新/插入频繁发生,导致每个分区中存在许多小文件。
题让我们看看小文件在查询时会如何导致题。当触发查询来提取或转换数据集时,驱动程序节点必须收集每个文件的元数据,这会在转换过程中产生性能开销。
解决方案定期压缩小文件有助于保持正确的文件大小,从而提高查询性能。ApacheHudi支持同步和异步压缩。
•同步压缩可以在写入过程本身期间启用,这会增加更新Hudi中记录的ETL执行时间。
•异步压缩压缩可以通过多种进程来实现,并且需要单独的内存来实现。这不会影响写入过程,并且是一个可扩展的解决方案。
Halodoc开创了同步压缩的先河。随着时间的推移,我们计划根据表大小、增长和用例采用混合压缩。
连帽衫包括
Hoodie数据源集群内联激活Hoodie数据源压缩异步保持存储大小以降低成本
仅仅因为数据湖便宜并不意味着您应该存储业务分析不需要的数据。否则,您很快就会发现您的存储成本越来越高。ApacheHudi维护每个upsert操作的文件版本,以服务对记录的时间遍历查询。每次提交都会创建文件的新版本,从而产生许多版本化文件。
题如果不启用清理策略,您的存储大小将呈指数级增长,直接影响您的存储成本。如果旧的提交没有商业价值,则应将其删除。
解决方案Hudi有两种组织策略基于文件版本和基于计数。Halodoc计算写入发生的频率以及ETL过程完成所需的时间,并基于此得出一些要保留在Hudi数据集中的提交。示例如果计划作业每5分钟将数据收集到Hudi中,并且运行时间最长的查询可能需要一个小时才能完成,则必须维护至少60/5=12次提交。
连帽衫包括
crowvacuumpolicy:KEEP_LATEST_COMMITScrowvacuumcommitmaintain:12或
hoodiecleanerpolicy:KEEP_LATEST_FILE_VERSIONShoodiecleanerfileversionsretained:1根据您的延迟和业务用例选择正确的存储类型。
ApacheHudi有两种存储数据集的存储类型,以适应不同的用例。一旦您选择了一种存储类型,更改/更新到另一种类型的过程可能会变得乏味。因此,在将数据迁移到Hudi数据集之前选择正确的存储类型非常重要。
题选择错误的存储类型可能会影响ETL执行时间和数据消费者的预期数据延迟。
解决方案Halodoc在其工作负载中使用这两种存储类型。MoRMoR代表读取时合并。我们为写入完成后需要立即读取访的表选择MoR。Hudi还维护增量更改日志的AVRO文件,并通过消除重建现有parquet文件的需要来减少更新插入时间。MoR为数据集_ro和_rt提供了两个视图。
•_ro用于读优化表。
•_rt用于实时表。
CoWCoW代表写入时复制。对于数据延迟、更新成本和写入放大优先级较低但读取性能优先级较高的数据集,选择存储类型CoW。
type=COPY_ON_WRITE/MERGE_ON_READhoodiedatasourcewritetabletype:类型文件列表很重,Hudi如何解决这个题?
对分布式对象存储或文件系统的更新插入和更新通常非常昂贵。这是因为这些系统本质上是不可变的,并且涉及跟踪和识别需要更新的文件子集,并用包含最新记录的新版本覆盖它们。ApacheHudi存储每个文件片段和文件组的元数据,以跟踪更新插入操作的历史记录。
题如前所述,不同分区中存在大量文件会导致驱动程序节点收集信息的开销,从而导致内存/计算题。
解决方案为了解决这个题,Hudi引入了元数据的概念,所有文件信息都存储在单独的表中,并在源发生变化时同步。这有助于Spark在一个位置读取或执行一系列文件,从而实现资源利用率。这可以通过以下配置轻松实现连帽衫配置
hoodiemetadataenabled:true为Hudi数据集选择正确的索引。
传统数据库中使用索引来有效地从表中检索数据。ApacheHudi也有索引的概念,但其工作方式略有不同。Hudi的索引主要用于强制表的所有分区中键的唯一性。
题如果您希望构建事务数据湖,那么在每个分区或全局中维护/重复记录始终很重要。
解决方案Hudi通过使用Hudi数据集上的索引来解决这个题,它提供了全局和非全局索引。默认情况下使用布隆索引。Hudi目前支持
•布隆索引使用基于记录键构建的布隆过滤器,并可以选择使用记录键范围来组织候选文件。
•简单索引对存储表中的记录和传入的更新/删除记录执行连接操作。
•Hbase索引管理外部ApacheHBase表的索引映射。
Halodoc利用全局Bloom索引来确保分区内的记录是唯一的。使用索引时,您需要根据源行为或是否希望某人保留副本来决定。
总结
在Halodoc,过去六个月我们一直在使用ApacheHudi,它很好地处理了我们的大型数据工作负载。为ApacheHudi选择正确的配置首先需要一些学习曲线。在这篇博客中,我们将分享构建LakeHouse时面临的一些挑战,以及在生产中使用ApacheHudi时适当配置参数/配置的一些实践。
关于mor 身体乳 博客和MOR身体乳的话题今天就聊到这,希望对大家有所帮助。