Apache Hudi 1.0 重点特性及下一代Lakehouse详解

Apache Hudi 1.0 重点特性及下一代Lakehouse详解

经验文章nimo972025-02-08 10:23:4713A+A-

概述

我们很高兴地宣布 Apache Hudi 1.0 的发布,这是我们充满活力的社区取得的里程碑式成就,它定义了下一代数据湖仓一体应该实现的目标。Hudi 在 2017 年率先推出了事务性数据湖,如今我们生活在一个技术类别作为“数据湖仓一体”成为主流的世界。与其他 OSS 替代方案出现时相比,Hudi 社区为这一类别做出了几项关键的、原创的和首创的贡献,如下所示。对于一个相对较小的 OSS 社区来说,在竞争激烈的商业数据生态系统中维持下去,这是一项非常罕见的壮举。另一方面,它也证明了在专注的开源社区中深入了解技术类别的价值。所以我首先要感谢/祝贺 Hudi 社区和 60+ 贡献者,他们使 1.0 成为现实。

版本[1]不仅仅是版本增量,它还提高了 Hudi 功能集的广度及其架构的稳健性,同时带来了新的创新来塑造未来。这篇文章回顾了技术和周围生态系统是如何演变的,为整体的“数据湖仓一体管理系统”(DLMS) 作为新的北极星提供了理由。在本文的大部分内容中,我们将深入探讨 Hudi 1.0 的最新功能,这些功能使这种演变成为可能。

数据湖仓一体的演变

技术必须根据新出现的需求不断发展 — Web 3.0[2]蜂窝技术[3]编程语言世代[4]。数据湖仓一体也不例外。本节探讨了数据湖仓一体用户的此类需求的层次结构。最基本的需求是 “表格式” 功能,这是数据湖仓一体的基础。表格式将文件/对象的集合组织到表中,并带有快照、架构和统计信息跟踪,从而实现更高的抽象性。此外,表格式决定了每个快照中文件的组织、编码删除/更新以及有关表如何随时间变化的元数据。表格式还为各种读取器和写入器以及表管理进程提供了协议,以处理并发访问并安全地提供 ACID 事务。在过去五年中,领先的数据仓库和云供应商已将其专有的 SQL 仓库堆栈与开放表格式集成。虽然它们大多默认使用其封闭的表格式,并且计算引擎保持关闭状态,但这一受欢迎的举措为用户提供了数据的开放替代方案。

但是格式的好处到此为止,现在表格格式只是冰山一角。用户需要端到端的开放数据湖仓一体[5],而现代数据湖仓一体功能需要一个复杂的开源软件层,用于处理以开放表格式存储的数据。例如,优化的写入器可以通过使用以表格格式或目录同步服务维护的统计数据仔细管理文件大小来平衡成本和性能,这些统计数据可以使 Hudi 中的数据随时可供打开和关闭的六个数据目录使用。Hudi 通过提供高性能的开放表格式以及全面的开源软件栈而大放异彩,这些栈可以摄取、存储、优化和有效地自行管理数据湖仓一体。开放格式和开放软件之间的这种区别在 Hudi 运营的大型供应商生态系统内部的转换中经常丢失。尽管如此,Hudi 的用户[6]避免对任何给定数据供应商的计算锁定一直是一个关键考虑因素。例如 Hudi Streamer 工具通过方便地在终端中通过单个命令从各种来源无缝摄取数据,为数百个数据湖提供支持。

在 1.0 中,社区对这些关键点进行了辩论[7],并得出结论,我们需要更多与 DBMS 直接相媲美的开源“软件功能”,主要有两个原因。

显著扩展数据湖仓一体的技术能力:Hudi 中的许多设计决策都受到数据库的启发(请参阅此处[8]的逐层映射),并为社区带来了显著的好处。例如,Hudi 的索引机制提供了该项目众所周知的快速更新性能。我们希望将这些功能推广到写入器和查询中,并引入新功能,例如用于查询规划的快速元存储、对非结构化/多模态数据的支持以及可以深度集成到生态系统中(至少)开源查询引擎的缓存机制。我们还需要适用于湖仓一体工作负载的并发控制,而不是在表面采用适用于 OLTP 数据库的技术。

我们还需要类似数据库的体验:我们最初将 Hudi 设计为一个软件库,可以嵌入到不同的查询/处理引擎中,用于读取/写入/管理表。此模型在现有数据生态系统中取得了巨大成功,该生态系统熟悉调度作业并使用多个引擎进行 ETL 和交互式查询。但是,对于想要探索数据湖仓一体的新用户来说,没有软件可以轻松安装和探索连贯打包的所有功能。这种数据湖仓一体功能像典型的数据库系统一样打包和交付,从而解锁了新的使用案例。例如借助这样的系统,我们可以以更快的云存储/面向行的格式将 HTAP 功能引入数据湖仓一体,最终使其成为低延迟数据服务层。

如果结合起来,我们将获得一个基于数据湖(房屋)架构构建的强大数据库,即我们认为行业需要的数据湖仓一体管理系统 (DLMS)。

Hudi 1.0 的主要功能

在 Hudi 1.0 中,我们在 Hudi 的存储引擎[9]层中提供了上面讨论的数据湖仓一体技术能力的重大扩展。存储引擎(又名数据库引擎)是位于存储/文件/表格式之上的标准数据库组件,由上面的 DBMS 层包装,处理核心读/写/管理功能。在下图中,我们将 Hudi 组件与开创性的数据库系统架构[10]论文(参见第 4 页)进行了映射,以说明所讨论的标准分层。如果分层实施得当,我们就可以通过 Apache XTable(孵化)[11]等项目中定义的互操作标准,将存储引擎的优势提供给其他表格式,这些格式可能缺乏如此完全开发的开源软件来管理表或实现高性能。

图:Apache Hudi 数据库架构

关于成熟的 DLMS 功能,Hudi 1.0 提供的最接近的体验是通过 Apache Spark。用户可以部署安装了 Hudi 1.0 的 Spark(或 Spark Connect),提交 SQL/作业,通过 SQL 命令编排表服务,并享受新的二级索引功能,以加快查询速度,就像 DBMS 一样。1.x 版本系列及更高版本中的后续版本将不断添加新功能并改进此体验。

在以下部分中,让我们深入了解是什么让 Hudi 1.0 成为出色的版本。

新时间和时间线

对于熟悉的用户来说,时间是 Hudi 中的一个关键概念。Hudi 最初的时间概念是瞬间的,即修改表格的动作似乎在给定的瞬间生效。这在设计跨写入器的非阻塞并发控制等功能时是有限的,这需要将操作更多地视为一个“间隔”来检测其他冲突的操作。Hudi 时间轴上的每个操作现在都会获得请求时间和完成时间;因此,时间轴布局版本在 1.0 版本中有所提高。此外为了便于用户和实现者理解并在时间生成方面保持一致性,我们已正式采用 TrueTime[12] 语义。默认实现确保即使使用分布式进程也能向前移动时钟,假设最大可容忍的时钟偏移类似于采用 TrueTime 的 OLTP/NoSQL[13] 存储。

图:显示 Hudi 1.0 中的操作,建模为两个时刻的间隔:请求和已完成

Hudi 表经常更新,用户还希望保留与表关联的扩展操作历史记录。在 Hudi 1.0 之前,表中较旧的操作历史记录被存档以供审计访问。但是由于缺乏对云存储附加的支持,由于大量小文件,访问可能会变得很麻烦。在 Hudi 1.0 中,我们将时间线重新设计为 LSM 树[14],这被广泛用于需要对时态数据进行良好写入性能的情况。

在 Hudi 1.0 版本中,LSM 时间线[15]被大量用于查询规划中,以在 Apache Spark、Apache Flink 和 Apache Hive 之间映射请求时间和完成时间。未来的版本计划利用这一点来统一时间线的活动和历史组件,从而提供表历史记录的无限保留。微观基准测试表明,LSM 时间线可以非常高效,甚至可以在 10 年内每 30 秒提交一次,大约有 10M 个瞬间,进一步巩固了 Hudi 的表格格式作为最适合频繁编写的表格的格式。

操作数即时批量大小读取成本 (仅次)读取成本(以及操作元数据)总文件大小
10000102 毫秒150 毫秒8.39MB
200001051 毫秒188 毫秒16.8MB
1000000010003400 毫秒162 秒8.4GB

用于更快查找的二级索引

索引是 Hudi 设计的核心,以至于即使是 Hudi 的第一个前开源版本也附带了索引[16]以加快写入速度。但是,这些索引仅限于写入端,除了上面 0.14+ 中的记录索引,这些索引也与 Spark SQL 查询集成在一起。Hudi 1.0 将索引泛化为更接近关系数据库中的索引功能,支持跨写入器和读取器对任何辅助列的索引。Hudi 1.0 还支持近乎标准的 SQL 语法[17],用于通过 Spark SQL 在不同列上创建/删除索引,以及异步索引表服务,以便在不中断写入器的情况下构建索引。

图:Hudi 1.0 中的索引子系统,显示了不同类型的索引

借助二级索引,查询和 DML 从云存储中扫描的文件数量大大减少,从而显著降低了成本(例如,在 AWS Athena 等引擎上,按扫描的数据定价),并提高了选择性较低甚至中等的查询的查询性能。在对表(来自 10 TB tpc-ds 数据集)web_sales查询的基准测试中,文件组 - 286,603,总记录数 - 7,198,162,544,二级索引列的基数在 ~ 1:150 范围内,我们看到延迟显著降低了 ~95%。

运行不跳过索引的总查询延迟(秒)跳过二级索引的总查询延迟 (秒)减少 %
125231~88%
221410~95%
32049~95%

在 Hudi 1.0 中,二级索引仅支持 Apache Spark,并计划在 Hudi 1.1 中支持其他引擎,从 Flink、Presto 和 Trino 开始。

Bloom Filter 索引

Bloom filter 索引在 Hudi 写入器上已经存在了很长时间。它是用户喜欢用于“大海捞针式”删除/更新或重复数据删除的最高性能、最通用的索引之一。该索引的工作原理是围绕最小/最大键范围在基本文件中存储特殊的页脚,以及一个适应文件大小的动态布隆过滤器,它可以自动处理写入器路径上的分区/倾斜。Hudi 1.0 为 Spark SQL 引入了一种较新的布隆过滤器索引,同时按原样保留写入器端索引。新索引将布隆过滤器存储在 Hudi 元数据表中,并将其他辅助/记录索引存储在 Hudi 元数据表中,以实现可扩展访问,即使对于大型表也是如此,因为与与数据文件一起存储相比,索引存储在更少的文件中。可以使用标准 SQL 语法[18]创建它,如下所示。对索引列的后续查询将使用 bloom 筛选条件来加快查询速度。

-- Create a bloom filter index on the driver column of the table `hudi_table`
CREATE INDEX idx_bloom_driver ON hudi_indexed_table USING bloom_filters(driver)
-- Create a bloom filter index on the column derived from expression `lower(rider)` of the table `hudi_table`
CREATE INDEX idx_bloom_rider ON hudi_indexed_table USING bloom_filters(rider) OPTIONS(expr='lower');

在 Hudi 的未来版本中,我们的目标是将旧写入端索引的优势完全集成到新的 bloom 索引中。尽管如此,这证明了 Hudi 的索引系统在处理表上不同类型索引方面的适应性。

分区已替换为表达式索引

精明的读者可能已经注意到,列上的函数/表达式支持索引。Hudi 1.0 引入了类似于 Postgres[19] 的表达索引,以概括数据湖生态系统中二十年前的遗迹——分区!概括地说,数据湖上的分区根据列或映射函数(分区函数)将表划分为多个文件夹。当对表执行查询或操作时,它们可以有效地跳过整个分区(文件夹),从而减少涉及的元数据和数据量。这非常有效,因为数据湖表跨越数百个数千个文件。但是听起来很简单,这是围绕数据湖性能的最常见陷阱[20]之一,新用户通过基于高基数列进行分区来将其用作索引,从而导致大量存储分区/小文件和糟糕的写入/查询性能。此外将存储组织与分区捆绑在一起使其无法灵活地应对更改。

图:当其他列对数据进行物理分区时,显示日期表达式上的索引

Hudi 1.0 将分区视为列值的粗粒度索引[21]或列的表达式,因为它们本来应该是这样的。为了支持跳过整个存储路径/文件夹的效率,Hudi 1.0 引入了分区统计索引,除了在文件级别这样做之外,还可以在存储分区路径级别聚合这些统计数据。现在用户可以在列上创建不同类型的索引,以简化的方式实现分区的效果,使用更少的概念来实现相同的结果。除了对其他 1.x 功能的支持外,分区统计和表达式索引支持将在 1.1 版本中扩展到其他引擎,如 Presto、Trino、Apache Doris 和 Starrocks。

高效的部分更新

管理大规模数据集通常涉及对记录进行精细更改。Hudi 长期以来一直支持通过记录有效负载接口对记录进行部分更新[22]。但是这通常是以牺牲引擎原生性能为代价的,因为它不再使用引擎用来表示行的特定对象。随着用户接受 Hudi 在 dbt/Spark 或 Flink 动态表之上的增量 SQL 管道,人们越来越有兴趣使其更加简单和主流。Hudi 1.0 在日志格式级别引入了对部分更新的一流支持,使 MERGE INTO SQL 语句能够仅修改记录的更改字段,而不是重写/重新处理整行。

部分更新通过减少写入的写入放大和 Merge-on-Read 快照查询读取的数据量,同时提高查询和写入性能。由于存储的字节数更少,它还实现了更好的存储利用率,并且通过保留矢量化引擎原生处理,与现有的部分更新支持相比,它还提高了计算效率。使用 1TB Brooklyn 写入性能基准测试,我们观察到,由于写入放大减少了 85%,读取时合并查询性能提高了约 2.6 倍。对于随机写入工作负载,增益可能要明显得多。下面显示了部分更新的第二个基准测试,1TB MOR 表,1000 个分区,80% 随机更新。3/100 列随机更新。


全记录更新部分更新收益
更新延迟 (s)207214291.4 倍
写入的字节数 (GB)891.712.770.2 倍
查询延迟 (s)164295.7 倍

这也为在 Hudi 表中管理非结构化和多模态数据以及为机器学习使用案例有效支持宽表[23]奠定了基础。

合并模式和自定义合并

Hudi 提供的最独特的功能之一是它如何帮助处理流数据。具体来说, Hudi 从一开始就支持使用预组合或排序字段在写入前(以减少写入放大)、写入期间(针对具有相同记录键的存储中的现有记录)和读取(用于 MoR 快照查询)合并记录。这有助于在数据湖仓一体存储上实现流处理系统广泛支持的事件时间处理[24]语义。这有助于将延迟到达的数据集成到 Hudi 表中,而不会导致记录状态的奇怪时间回溯。例如,如果较旧的数据库 CDC 记录延迟到达并被提交为新值,则即使对表本身的写入是按某种顺序序列化的,该记录的状态也会不正确。

图:显示了合并根据最高event_time对状态进行协调的EVENT_TIME_ORDERING

以前的 Hudi 版本通过记录有效负载接口支持此功能,并内置了对默认有效负载上的预组合字段的支持。Hudi 1.0 通过在 Hudi 中引入合并模式[25],使这两种处理和合并更改风格成为一流的。

合并模式它有什么作用?
COMMIT_TIME_ORDERING选择具有最高完成时间/时刻的记录作为最终合并结果,即标准关系语义或到达时间处理
EVENT_TIME_ORDERINGDefault (目前,为了简化迁移)。为用户指定的排序/预组合字段选择具有最高值的记录作为最终合并结果。
CUSTOM使用用户提供的 RecordMerger 实现生成最终合并结果(类似于流处理处理器 API)

与部分更新支持一样,新的 RecordMerger API 通过原生对象和EVENT_TIME_ORDERING合并模式下的向量化处理,为旧的 RecordPayload 接口提供了更高效的引擎原生替代方案。在未来的版本中,我们打算将默认值更改为 COMMIT_TIME_ORDERING 以提供简单、开箱即用的关系表语义。

流式写入的非阻塞并发控制

我们对数据湖仓一体上采用的乐观并发控制方法表示不太满意,因为它们似乎笼统地描绘了问题,而没有注意湖仓一体工作负载的细微差别。具体来说,争用在数据湖仓一体中更为常见,即使对于 Hudi 也是如此,Hudi 是唯一一个能够异步压缩增量更新而不会失败或导致写入器重试的数据湖仓一体存储项目。归根结底,数据湖仓一体是高吞吐量系统,如果并发写入器无法处理争用,可能会浪费昂贵的计算集群。流式处理和高频写入通常需要精细的并发控制,以防止出现瓶颈。

Hudi 1.0 引入了一种新的非阻塞并发控制 (NBCC),该控制专为数据湖仓一体工作负载而设计,利用了多年来在 Hudi 社区中支持地球上一些最大的数据湖的经验。NBCC 支持从多个写入器同时写入和压缩同一记录,而不会阻止任何涉及的进程。这是通过上面讨论的简单轻量级分布式锁和 TrueTime 语义来实现的。(有关详细信息,请参阅 RFC-66[26]

图:两个正在运行的流式处理作业同时写入不同列上的相同记录。

NBCC 使用流式语义进行操作,将前面几节中的概念捆绑在一起。计算表更新所需的数据是从上游源发出的,并且更改和部分更新可以在上述任何合并模式中合并。例如在上图中,两个独立的 Flink 作业并行丰富了不同的表列,这是流处理使用案例中普遍存在的模式。查看此博客[27]以获取完整演示。我们还希望在未来的版本中支持其他计算引擎的 NBCC。

向后兼容写入

如果你想知道:“这一切听起来很酷,但我该如何升级?”我们已经花了很多心思来实现无缝衔接。Hudi 始终支持对旧表版本的向后兼容读取。表版本存储在与软件二进制版本无关的表属性中。支持的升级方式是首先将读取器/查询引擎迁移到新的软件二进制版本,然后升级写入器,如果新旧软件二进制版本之间存在表版本更改,这将自动升级表。根据社区反馈,用户表示需要能够在不等待读取端升级的情况下对写入端进行升级,并减少不同团队内部必要的任何额外协调。

图:轻松滚动升级到 Hudi 1.0 的 4 步流程

如上所述,Hudi 1.0 引入了向后兼容写入,可以通过 4 个步骤实现这一目标。Hudi 1.0 还会自动处理任何必要的检查点转换,因为我们为增量查询和 CDC 查询切换到基于完成时间的处理语义。在此升级过程中,必须暂时禁用 Hudi 元数据表,但可以在升级成功完成后打开。请仔细阅读发行说明[28]以规划迁移。

下一步计划?

Hudi 1.0 证明了开源协作的力量。此版本体现了 60+ 开发人员、维护人员和用户的贡献,他们积极塑造了其路线图。我们衷心感谢 Apache Hudi 社区的热情、反馈和坚定不移的支持。

Hudi 1.0 的发布只是一个开始。我们当前的路线图[29]包括以下计划版本中令人兴奋的发展:

  • ? 1.0.1:第一个错误修复,在 1.0 的基础上发布补丁,它强化了上述功能并使其更容易。我们打算发布其他补丁版本,以帮助从 0.x 迁移到 1.0 作为社区的 Bridge 版本。

  • ? 1.1:更快的写入器代码路径重写、位图/向量化搜索等新索引、精细记录级更改编码、Hudi 存储引擎 API、跨格式互操作的抽象。

  • ? 1.2:多表事务、Hudi 等反向流式处理平台服务、多模态数据 + 索引、NBCC 聚类

  • ? 2.0:用于 DLMS、缓存和元服务器功能的服务器组件。

Hudi 版本由社区协作起草。如果在此处没有看到喜欢的内容,请帮助一起制定路线图。

开始使用 Apache Hudi 1.0

你准备好体验数据湖仓一体的未来了吗?以下是深入了解 Hudi 1.0 的方法:

  • ? 文档:探索 Hudi 的文档[30]并学习概念[31]

  • ? 快速入门指南:按照快速入门指南[32]设置您的第一个 Hudi 项目。

  • ? 从以前的版本升级?按照迁移指南[33]进行操作,并联系 Hudi OSS 社区寻求帮助。

  • ? 加入社区:参与 Hudi 邮件列表[34]Slack[35]GitHub[36] 上的讨论。

  • ? 在社交媒体上关注我们:LinkedIn[37]X/Twitter[38]

我们迫不及待地想看看使用 Apache Hudi 1.0 构建了什么。让我们共同努力,塑造数据湖仓一体的未来!

引用链接

[1] 版本: https://hudi.apache.org/releases/release-1.0.0
[2] Web 3.0: https://en.wikipedia.org/wiki/Web3
[3] 蜂窝技术: https://en.wikipedia.org/wiki/List_of_wireless_network_technologies
[4] 编程语言世代: https://en.wikipedia.org/wiki/Programming_language_generations
[5] 端到端的开放数据湖仓一体: https://www.onehouse.ai/blog/open-table-formats-and-the-open-data-lakehouse-in-perspective
[6] 的用户: https://hudi.apache.org/powered-by
[7] 进行了辩论: https://github.com/apache/hudi/pull/8679
[8] 此处: https://github.com/apache/hudi/blob/master/rfc/rfc-69/rfc-69.md#hudi-1x
[9] 存储引擎: https://en.wikipedia.org/wiki/Database_engine
[10] 数据库系统架构: https://dsf.berkeley.edu/papers/fntdb07-architecture.pdf
[11] Apache XTable(孵化): https://xtable.apache.org/
[12] TrueTime: https://hudi.apache.org/docs/timeline#truetime-generation
[13] OLTP/NoSQL: https://cockroachlabs.com/blog/living-without-atomic-clocks/
[14] LSM 树: https://en.wikipedia.org/wiki/Log-structured_merge-tree
[15] LSM 时间线: https://hudi.apache.org/docs/timeline#lsm-timeline-history
[16] 索引: https://hudi.apache.org/docs/indexes#additional-writer-side-indexes
[17] SQL 语法: https://hudi.apache.org/docs/sql_ddl#create-index
[18] SQL 语法: https://hudi.apache.org/docs/sql_ddl#create-bloom-filter-index
[19] Postgres: https://www.postgresql.org/docs/current/indexes-expressional.html
[20] 最常见陷阱: https://www.onehouse.ai/blog/knowing-your-data-partitioning-vices-on-the-data-lakehouse
[21] 粗粒度索引: https://hudi.apache.org/docs/sql_queries#query-using-column-stats-expression-index
[22] 部分更新: https://hudi.apache.org/docs/0.15.0/record_payload#partialupdateavropayload
[23] 宽表: https://github.com/apache/hudi/pull/11733
[24] 的事件时间处理: https://www.oreilly.com/radar/the-world-beyond-batch-streaming-101/
[25] 合并模式: https://hudi.apache.org/docs/record_merger
[26] RFC-66: https://github.com/apache/hudi/blob/master/rfc/rfc-66/rfc-66.md
[27] 博客: https://hudi.apache.org/blog/2024/12/06/non-blocking-concurrency-control
[28] 发行说明: https://hudi.apache.org/releases/release-1.0.0
[29] 路线图: https://hudi.apache.org/roadmap
[30] 的文档: https://hudi.apache.org/docs/overview
[31] 概念: https://hudi.apache.org/docs/hudi_stack
[32] 快速入门指南: https://hudi.apache.org/docs/quick-start-guide
[33] 迁移指南: https://hudi.apache.org/releases/release-1.0.0#migration-guide
[34] Hudi 邮件列表: https://hudi.apache.org/community/get-involved/
[35] Slack: https://join.slack.com/t/apache-hudi/shared_invite/zt-2ggm1fub8-_yt4Reu9djwqqVRFC7X49g
[36] GitHub: https://github.com/apache/hudi/issues
[37] LinkedIn: https://www.linkedin.com/company/apache-hudi/?viewAsMember=true
[38] X/Twitter: https://twitter.com/ApacheHudi


点击这里复制本文地址 以上内容由nimo97整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

尼墨宝库 © All Rights Reserved.  蜀ICP备2024111239号-7