Apache Hudi 从零到一:初识 Hudi 的存储格式(一)
导读 本文介绍了 Apache Hudi 从零到一:初识 Hudi 的存储格式(一),翻译自原英文博客 https://blog.datumagic.com/p/apache-hudi-from-zero-to-one-110(SHIYAN XU AUG 28, 2023)。
主要内容包括以下几个部分:1. Hudi 概述
2. 存储格式
3. 回顾
分享嘉宾|许世彦 Onehouse 开源项目负责人
编辑整理|王甲君
出品社区|DataFun
在花了大约四年时间致力于 Apache Hudi(其中包括三年 Committer 身份)之后,我决定开始写这个博客系列,旨在有结构性的且以适合初学者的方式展示 Hudi 的设计和用法。目标是确保对分布式数据系统有一定了解的读者能够轻松地理解该系列。这个系列将包含十篇文章,每篇深入探讨 Hudi 的一个关键方面。(为什么是十篇?纯粹是对 0 和 1 的有趣致敬,与标题呼应。)最终目标是帮助读者从广度和深度上理解 Hudi,使他们能够自信地利用这个开源项目并为其做出贡献。
01
Hudi 概述
Hudi 是一个事务型数据湖平台,它将数据库和数据仓库的功能带到了数据湖中。下面展示的 Hudi 架构清晰地说明了该平台的主要特性。
在核心层面,Hudi 定义了一种表格式,用于在存储系统中组织和表示数据及其元数据文件,从而实现 ACID 事务、高效索引和增量处理等特性。本文剩余部分将探讨这种表格式的细节,主要展示 Hudi 表在存储中的结构,并解释不同文件的作用。
02
存储格式
以下图表描述了 Hudi 表在存储中基础路径下的典型数据布局。
主要有两种类型的文件:
位于 <base_path>/.hoodie/ 目录下的元数据文件
存储在分区路径中(如果表已分区)的数据文件,或者直接在基本路径(如果未分区)下的数据文件
1. 元数据
<base path>/.hoodie/hoodie.properties 文件包含了表的关键配置,如表名和版本,这些配置都会被表的写入者和读取者所遵循和使用。
除了 hoodie.properties 之外,还有一些元数据文件记录了对表的事务性操作,这些元数据文件构成了 Hudi 表的 Timeline。
# an example of deltacommit actions on Timeline
20230827233828740.deltacommit.requested
20230827233828740.deltacommit.inflight
20230827233828740.deltacommit
这些元数据文件遵循以下命名模式:
<action timestamp>.<action type>[.<action state>]
“action timestamp”
标记了一个操作首次被安排执行的时间。
在 Timeline 中唯一标识一个操作。
在 Timeline 的不同操作之间单调递增。
“action type”表示该操作进行了哪种类型的更改。有写入操作类型,如 commit 和 deltacommit,表示在表上发生了新的写入操作(插入、更新或删除)。此外,还有表服务操作,如 compaction 和 clean,以及恢复操作(如 savepoint 和 restore)。我们将在未来的文章中更详细地讨论不同的操作类型。
“action state”可以是 requested、inflight 或 completed(没有后缀)。顾名思义,requested 表示该操作已被安排执行,inflight 表示正在执行中,而 completed 表示操作已完成。
这些操作的元数据文件,采用 JSON 或 AVRO 格式,包含有关应用于表或已应用于表的更改信息。保留这些事务日志使得可以重新创建表的状态,实现快照隔离,并通过并发控制机制解决写入冲突。
在“.hoodie/”目录下还存储了其他元数据文件和目录。例如,“metadata/”目录包含与 Timeline 上的操作相关的更多元数据,并为读者和写入者提供索引。“.heartbeat/”目录存储心跳管理文件,而“.aux/”目录则保留用于各种辅助目的。
2. 数据
Hudi 将物理数据文件分为基本文件(Base File)和日志文件(Log File):
基本文件包含 Hudi 表中主要存储的记录,并针对读取进行了优化。
日志文件包含在其关联的基本文件之上的记录更改,并针对写入进行了优化。
在 Hudi 表的分区路径内(如之前布局图所示),单个基本文件及其关联的日志文件(可能为零个或多个)被组合成一个文件切片(File Slice)。多个文件切片构成一个文件组(File Group)。文件组和文件切片都是设计用于封装物理文件的逻辑概念,以简化读取器和写入器的访问和操作。通过定义这些模型,Hudi 可以:
同时满足读取和写入的效率要求。通常,基本文件被配置为列式文件格式(如Apache Parquet),而日志文件被设置为基于行的文件格式(如 Apache Avro)。
通过提交操作实现版本控制。每个文件切片都与 Timeline 上某个特定操作的时间戳相关联,而文件组内的文件切片实质上跟踪了所包含记录随时间的变化情况。
3. 表类型
Hudi 定义了两种表类型 - 写时复制(Copy-on-Write,简称 CoW)和读时合并(Merge-on-Read,简称 MoR)。它们的布局差异如下:与 MoR 相比,CoW 没有日志文件,并且写操作会产生“.commit”动作而不是“.deltacommit”。在我们的讨论中,我们一直以 MoR 作为示例。一旦掌握了 MoR,理解 CoW 就变得很简单了——可以将 CoW 视为 MoR 的一个特例,其中在每个写操作期间,基本文件中的记录和更改都隐式地合并到一个新的基本文件中。
在为 Hudi 表选择表类型时,重要的是要考虑读写模式,因为有一些隐含的影响:
CoW 由于每次写入都需要在新文件切片中重写记录,因此具有较高的写放大率,但读取操作始终会被优化。这非常适合以读取为主的分析工作负载或小表。
MoR 具有较低的写放大率,因为更改被缓存在日志文件中,并批量处理以合并和创建新的文件切片。然而,读取延迟会受到影响,因为读取最新记录时需要合并日志文件与基本文件。
用户还可以选择仅读取 MoR 表的基本文件以获得效率,同时牺牲结果的实时性。我们将在后续文章中讨论 Hudi 的不同读取模式。随着 Hudi 项目的不断发展,与从 MoR 表读取相关的合并成本在过去几个版本中得到了优化。可以预见,MoR 将成为大多数工作负载场景的首选表类型。
03
回顾
在“Hudi 从零到一”系列的第一篇博文中,我们探讨了 Hudi 存储格式的基本概念,以阐明 Hudi 表中元数据和数据的结构。我们还简要解释了不同的表类型及其权衡。如概述图所示,Hudi 作为一个全面的数据湖平台,提供了各种维度的功能。在接下来的九篇博文中,我将逐步介绍该平台的其它重要方面。欢迎关注 Hudi 公众号 ApacheHudi 获取微信群信息,加入钉钉群:35087066,发送空邮件至 dev-subscribe@hudi.apache.org 参与讨论。
分享嘉宾
INTRODUCTION
许世彦
Onehouse
开源项目负责人
Onehouse 创始团队成员,开源项目负责人。Apache Hudi PMC 成员。
往期推荐
对话刘铭教授:多模态知识图谱构建初探
推荐系统降本增效之路
强化学习在推荐系统中的实践探索与业界进展
大模型驱动的数据清洗与数据合规技术展望
DataFunCon2024·北京站,精彩议题抢先看!
欧美 KOL 游戏营销技术应用
加速数据决策,实时数仓创新应用与实践
AI 技术演进与商业落地:从学术探索到创业实践的全景观察
小米公司 Con 2024-Agent 技术在语音助手场景中的应用
点个在看你最好看
SPRING HAS ARRIVED