Apache Hudi 社区正在对 Apache Hudi 1.x版本功能进行讨论,欢迎感兴趣同学参与讨论,PR链接:https://github.com/apache/hudi/pull/8679 或点击原文链接。
摘要
此 RFC[1]提议对 Hudi 中的事务数据库层进行令人兴奋和强大的重构,以推动未来几年整个社区的持续创新。在过去的几年里,社区成长[2] 超过 6 倍的贡献者,这个 RFC 是围绕核心愿景澄清和调整社区的绝佳机会。此 RFC 旨在作为此讨论的起点,然后征求反馈、接受新想法并协作建立共识,以实现有影响力的 Hudi 1.X 愿景,然后提炼出构成第一个版本——Hudi 1.0 的内容。
项目状态
众所周知,Hudi 最初于 2016 年在 Uber 创建,用于解决 大规模数据摄取[3]和 增量数据处理[4] 问题,后来 捐赠[5] 给 ASF。自 2020 年作为顶级 Apache 项目毕业以来,社区在 流数据湖愿景[6],通过在一组强大的平台组件之上进行增量处理,使数据湖更加实时和高效。最新的 0.13 汇集了几个显着的功能来增强增量数据管道,包括 RFC-51 Change Data Capture[7],更高级的索引技术consistent hash indexes[8] 和诸如 早期冲突检测[9] 之类的创新。
如今 Hudi 用户[10] 能够使用 Hudi 作为数据湖平台解决终端用例,该平台在可互操作的开放存储格式之上提供大量自动化。用户可以从文件/流系统/数据库中增量摄取,并将该数据插入/更新/删除到 Hudi 表中,并提供多种高性能索引选择。由于记录级元数据和增量/CDC 查询等核心设计选择,借助强大的流处理支持,用户能够始终如一地将摄取的数据链接到下游管道,近年来在 Apache Spark、Apache Flink 和 Kafka Connect 等框架中。Hudi 表格服务会自动处理这些摄取和派生的数据,以管理表格簿记、元数据和存储布局的不同方面。最后,Hudi 对不同目录的广泛支持和跨各种查询引擎的广泛集成意味着 Hudi 表也可以“批量”处理老式风格或从交互式查询引擎访问。
未来的机会
我们一直在 0.x 版本中添加新功能,但我们也可以将 Hudi 的核心变成更通用的湖数据库体验。作为 lakehouse 的第一个实现(我们称之为“交易数据湖”或“流数据湖”,分别是仓库用户和数据工程师的语言),我们根据当时的生态系统做了一些保守的选择。然而,重新审视这些选择很重要,以便看看它们是否仍然有效。
• 深度查询引擎集成: 当时 Presto、Spark、Flink、Trino 和 Hive 等查询引擎擅长查询列式数据文件,但很难集成到其中。随着时间的推移,我们期望清晰的 API 抽象围绕 parquet/orc 读取路径中的索引/元数据/表快照,像 Hudi 这样的项目可以利用这些路径轻松利用像 Velox/PrestoDB 这样的创新。然而大多数引擎更喜欢单独的集成——这导致 Hudi 维护自己的 Spark 数据源,Presto 和 Trino 连接器。然而现在这为在查询计划和执行期间充分利用 Hudi 的多模式索引功能提供了机会。
• 广义数据模型: 虽然 Hudi 支持主键,但我们专注于更新 Hudi 表,就好像它们是键值存储一样,而 SQL 查询在上面运行,保持不变并且无感知。当时根据生态系统的位置推广对主键的支持还为时过早,因为生态系统仍在执行大批量 MR 作业。如今,Apache Spark 和 Apache Flink 等性能更高的高级引擎具有成熟的可扩展 SQL 支持,可以支持 Hudi 表的通用关系数据模型。
• 有服务器和无服务器: 数据湖历来都是关于定期或按需触发的作业。尽管许多元数据扩展挑战可以通过精心设计的元服务器来解决(类似于现代云仓库所做的),社区一直对除了数据目录或 Hive 元服务器之外的长期运行服务犹豫不决。事实上我们的时间线服务器由于社区缺乏共识工作停滞不前。然而随着并发控制等需求的发展,出现了围绕开放格式的这些问题的专有解决方案。现在可能是时候通过采用混合架构来为社区转向真正开放的解决方案了,在该架构中,我们为表元数据使用服务器组件,同时为数据保留无服务器。
• 除了结构化数据:即使我们解决了有关在 parquet/avro/orc 中摄取、存储、管理和转换数据的挑战,仍然有大多数其他数据无法从这些功能中受益。使用 Hudi 的 HFile 表进行 ML 模型服务是一个新兴的用例,用户希望以低成本、轻量级的方式直接从湖存储中提供计算数据。通常,非结构化数据,如 JSON 和 blob类似的图像必须使用某种结构进行伪建模,从而导致性能或可管理性不佳。随着近年来 AI/ML 的迅速崛起,像 Hudi 这样的项目缺乏对复杂、非结构化、大 blob 的支持,只会让数据碎片化在湖泊中。为此,我们需要支持所有主要的图像、视频和 ML/AI 格式,并在索引、变异或捕获变化方面具有相同深度的功能。
• 更强大的自我管理:Hudi 在开源数据湖管理方面提供了当今最广泛的功能集,从摄取数据到优化数据以及自动化各种簿记活动以自动管理表数据和元数据。看到社区如何使用这个管理层来提升他们的数据湖体验令人印象深刻。
但是,我们有很多功能要添加,例如,反向流数据到其他系统或快照管理[11]或诊断报告器[12] 或跨地域逻辑复制或记录级 生存时间管理[13]
Hudi 1.X
鉴于我们更像是一个数据库问题来处理 Hudi,因此 Hudi 有许多构成数据库的构建块也就不足为奇了。从开创性的数据库系统架构论文[14](参见第 4 页)中绘制基线,我们可以看到 Hudi 如何构成针对湖优化的数据库的下半部分,具有多个查询引擎层 - SQL、编程访问、专门用于 ML /AI、实时分析和其他引擎处于领先地位。下面的主要区域直接映射了我们如何跟踪 Hudi 路线图。我们将看到我们如何专门针对数据湖的规模和湖工作负载的特征调整这些组件。
突出显示现有(绿色)和新(黄色)Hudi 组件以及外部组件(蓝色)的参考图。
数据库中的日志管理器组件有助于组织日志,以便在崩溃期间恢复数据库等。在事务层,Hudi 实现了将数据组织到文件组和文件切片中的方法,并将修改表状态的事件存储在时间轴中。Hudi 还使用标记文件跟踪进行中的事务以实现有效回滚。由于该湖存储的数据比典型的操作数据库或数据仓库多得多,同时需要更长的记录版本跟踪,因此 Hudi 生成了记录级元数据,可以很好地压缩以帮助更改数据捕获或增量查询等功能,有效地将数据本身视为日志 . 未来我们希望继续完善 Hudi 的数据组织,提供可扩展的、无限的时间线和数据历史、时间旅行写入、存储联邦等功能。
锁管理器组件有助于在数据库中实现并发控制机制。Hudi 附带了几个外部锁管理器,尽管我们最终希望通过我们今天仅提供时间线元数据的元服务器[15]来简化这一点。这篇论文(第 81 页)描述了数据库中常见的并发控制技术之间的权衡:2Phase Locking(没有中央事务管理器很难实现)、OCC(在没有争用的情况下工作良好,在争用时效率很差)和 MVCC(收益率 高吞吐量,但在某些情况下放松了可串行化性)。Hudi 在并发写入器之间实现了 OCC,同时为写入器和表服务提供了基于 MVCC 的并发,以避免它们之间的任何阻塞。退一步,我们需要问问自己,如果我们正在构建一个 OLTP 关系数据库,以避免盲目地将适用于它们的相同并发控制技术应用到写入湖的高吞吐量管道/作业的陷阱。Hudi 并不是非常倾向于 OCC ,并鼓励通过输入流序列化更新/删除/插入,以避免 OCC 对快速变化的表或流式工作负载造成性能损失。即使我们实施了早期冲突检测等技术来改进 OCC,此 RFC 也建议 Hudi 应该追求更通用的基于非阻塞 MVCC 的并发控制,同时为简单和批量附加的用例保留 OCC。
访问方法组件包括索引、元数据和存储布局组织技术,这些技术暴露给数据库的读/写。去年我们新增了多模态索引[16],支持基于MVCC的异步建索引[17],建索引时不阻塞写者,建完后仍与表数据保持一致。到目前为止,我们的重点一直更狭隘地针对使用索引技术来提高写入性能,而查询则受益于文件和列统计元数据以进行规划。未来我们希望支持在写入和查询中统一使用各种索引类型,以便可以在 Hudi 的索引之上高效地规划、优化和执行查询。由于 Hudi 的连接器适用于 Presto、Spark 和 Trino 等流行的开源引擎,现在这成为可能。已经添加了新的二级索引方案[18]和内置索引函数的建议,以索引从列派生的值。
缓冲区管理器组件管理脏存储块并缓存数据以加快查询响应速度。在 Hudi 的上下文中,我们希望让我们现在期待已久的列式缓存服务[19]焕发生机,该服务可以透明地位于湖存储和查询引擎之间,同时了解事务边界和记录突变。 RUM 猜想[20]详细介绍了设计平衡读取、更新和内存成本的系统的权衡。我们这里的基本想法是优化读取(从缓存中提供更快的查询)和更新(通过不断压缩内存来分摊 MoR 合并成本)成本,同时将缓存/内存成本添加到系统中。目前,这个想法可能有很多候选设计,我们需要一个单独的设计/RFC 来实现它们。
共享组件包括复制、加载和各种实用程序,以及目录或元数据服务器。大多数数据库隐藏了底层格式/存储的复杂性,为用户提供了许多数据管理工具。Hudi 也不例外,Hudi 拥有久经考验的批量和连续数据加载实用程序(deltastreamer、flinkstreamer 工具以及 Kafka Connect Sink)、一套全面的表服务(清理、归档、压缩、集群、索引……)、admin CLI 等等。社区一直致力于开发新的服务器组件,例如元服务器[21],它可以扩展为使用高级数据结构(例如区域映射/间隔树)或表服务管理器[22]来索引表元数据,以集中管理 Hudi 表。我们很乐意朝着拥有一组水平可扩展、高度可用的元服务器的方向发展,这些元服务器可以提供这些功能以及一些锁管理功能。另一个有趣的方向是反向加载器/流数据实用程序,它也可以将数据从 Hudi 移出到其他外部存储系统中。
总而言之我们提出 Hudi 1.x 作为 Hudi 的重新构想,作为湖的事务数据库,具有多语言持久性,将 Hudi 数据湖的抽象和平台化水平提高到更高。
Hudi 1.0 发布
本节概述了第一个 1.0 版本目标和可能必须进行的前端加载更改。此 RFC 征求社区的更多反馈和贡献,以扩大范围或在 1.0 版本中为用户提供更多价值。
简而言之,我们提出 Hudi 1.0 尝试并实现以下目标。
• 合并对格式的所有/任何更改 - 时间线、日志、元数据表...
• 跨表元数据、快照、索引/元数据表、主键生成、记录合并等建立新的 API(如果有的话)
• 将内部代码分层/抽象到位 - 例如 HoodieData、文件组读取器/写入器、存储...
• 以配置保护的安全方式登陆所有主要的、杰出的 "needle mover" PR
• 集成 Spark/Flink/Presto 的部分/全部现有索引,并验证预期的功能和性能提升。
所有更改都应向后兼容,并且不需要重写现有表中的基本/镶木地板文件。但是,从 0.x 版本迁移到 1.0 版本时,可能需要完全压缩日志或计划停机时间以重写时间线或重建元数据表。
该 RFC 将通过对 Hudi 不同部分的具体更改进行扩展。请注意此 RFC 仅用于识别这些领域,对于影响存储格式、向后兼容性或新公共 API 的任何更改,应给出单独的 RFC。
推出/采用计划
我们建议 1.0 的执行在下面的三个版本系列中完成。
• alpha(2023 年 7 月):所有格式更改均已落地,内部代码分层/抽象工作,主要未完成的 PR 已安全落地。0.X 表可以无缝升级,核心 Hudi 写入/查询流程经过认证。
• beta(2023 年 8 月):添加了新的 API,更改了代码路径以使用新的 API,索引集成了性能/功能资格。
• Generally available(2023 年 9 月):在一般发布之前由社区进行规模测试、压力测试和生产强化。