Apache Hudi从零到一:存储格式初探
在花了大约 4 年时间致力于 Apache Hudi(其中包括 3 年Committer身份)之后,我决定开始这个博客系列,旨在以有组织且适合初学者的方式展示 Hudi 的设计和用法。 我的目标是确保对分布式数据系统有一定了解的人能够轻松地理解该系列。 该系列将包含 10 篇文章,每篇文章都会深入探讨 Hudi 的一个关键方面。 (为什么是 10?纯粹是对 0 和 1 的有趣致敬,与系列标题相呼应:))最终目标是帮助读者从广度和深度上理解 Hudi,使他们能够自信地利用这个开源项目并为其做出贡献。 在撰写本文时,Hudi 0.14.0 正处于候选版本阶段。 因此,整个系列以及配套代码和示例都将基于此版本。
概述
Hudi 是一个事务性数据湖平台,它将数据库和数据仓库功能引入数据湖。 下图摘自 Hudi 社区举办的网络研讨会,清楚地说明了该平台的主要功能

Hudi 的核心定义了一种表格式,用于组织存储系统内的数据和元数据文件,从而实现 ACID 事务、高效索引和增量处理等功能。 本文的其余部分将探讨格式详细信息,主要展示存储上的 Hudi 表的结构并解释不同文件的角色。
存储格式
下图描述了 Hudi 表在存储中的基本路径下的典型数据布局。

有两种主要类型的文件:位于 .hoodie/ 目录中的元数据文件,以及存储在分区路径中(如果表已分区)的数据文件,或者直接在基本路径(如果未分区)下的数据文件。
元数据
<base path>/.hoodie/hoodie.properties 文件包含基本的表配置,例如表名称和版本,表的写入端和读取端都将遵守和使用这些配置。
除了 hoodie.properties 之外,还有将事务操作记录到表中的元文件,形成 Hudi 表的时间轴。
# an example of deltacommit actions on Timeline
20230827233828740.deltacommit.requested
20230827233828740.deltacommit.inflight
20230827233828740.deltacommit
这些元文件遵循以下命名模式:
<action timestamp>.<action type>[.<action state>]
"action timestamp"
- 标记第一次计划运行操作的时间。
- 唯一标识时间轴上的操作。
- 在时间轴上的不同操作之间单调递增。
"action type"显示该动作做出了什么样的改变。 有一些写入操作类型,例如 commit 和 deltacommit,它们指示表上发生的新写入操作(插入、更新或删除)。 此外,还有表服务操作,例如压缩和清理,以及恢复操作,例如保存点和恢复。 我们将在以后的帖子中更详细地讨论不同的操作类型。
"action state"可以是“已请求”、“进行中”或“已完成”(没有后缀)。 顾名思义,“已请求”表示正在计划运行,“正在执行”表示正在进行中,“已完成”表示操作已完成。
这些操作的元文件采用 JSON 或 AVRO 格式,包含有关应应用于表或已应用的更改的信息。 保留这些事务日志可以重新创建表的状态,实现快照隔离,并通过并发控制机制协调写入器冲突。
.hoodie/ 下还存储有其他元数据文件和目录。 举一些例子,元数据包含与时间轴上的操作相关的更多元数据,并充当写入端和读取端的索引。 .heartbeat/ 目录存储用于心跳管理的文件,而 .aux/ 则保留用于各种辅助目的。
数据
Hudi将物理数据文件分为Base File(基本文件)和Log File(日志文件):
- 基本文件包含 Hudi 表中的主要存储记录,并针对读取进行了优化。
- 日志文件包含其关联基本文件之上的记录更改,并针对写入进行了优化。
在 Hudi 表的分区路径中(如前面的布局图所示),单个基本文件及其关联的日志文件(可以没有或多个)被分组在一起作为文件切片。 多个文件切片构成一个文件组。 文件组和文件切片都是逻辑概念,旨在封装物理文件,从而简化读取端和写入端的访问和操作。 通过定义这些模型,Hudi 可以
- 满足读写效率要求。 通常基本文件配置为列式文件格式(例如 Apache Parquet),日志文件设置为基于行的文件格式(例如 Apache Avro)。
- 实现跨提交操作的版本控制。 每个文件切片都与时间轴上操作的特定时间戳相关联,文件组中的文件切片本质上跟踪所包含的记录如何随时间演变。
可以快速查看此处的 Hudi 表示例,了解数据布局。
表格类型
Hudi 定义了两种表类型 - 写入时复制 (CoW) 和读取时合并 (MoR)。 布局差异如下:与 MoR 相比,CoW 没有日志文件,并且写入操作会导致 .commit 操作而不是 .deltacommit。 在我们的讨论中,我们一直以 MoR 为例。 一旦掌握了 MoR,理解 CoW 就变得简单了 - 可以将 CoW 视为 MoR 的特殊情况,其中基本文件中的记录和更改在每次写入操作期间隐式合并到新的基本文件中。 可以在此处浏览示例 CoW 表。
在为 Hudi 表选择表类型时,考虑读取和写入模式非常重要,因为这会产生一些影响:
- 由于每次写入都会重写新文件切片中的记录,因此 CoW 具有较高的写入放大,而读取操作始终会得到优化。 这非常适合读取繁重的分析工作负载或小型表。
- MoR 的写入放大较低,因为更改会“缓冲”在日志文件中,并进行批处理以合并和创建新的文件切片。 但是,读取延迟会受到影响,因为读取最新记录需要将日志文件与基本文件进行实时合并。
用户还可以选择仅读取 MoR 表的基本文件,以提高效率,同时牺牲结果的新鲜度。 我们将在接下来的帖子中详细讨论 Hudi 的不同阅读模式。 随着 Hudi 项目的发展,与从 MoR 表读取相关的合并成本在过去的版本中得到了优化。 可以预见 MoR 将成为大多数工作负载场景的首选表类型。
回顾
在零到一系列的第一篇文章中,我们探讨了 Hudi 存储格式的基本概念,以阐明元数据和数据在 Hudi 表中的结构。 我们还简要解释了不同的表类型及其权衡。 如概览图所示,Hudi 作为一个综合性 Lakehouse 平台,提供不同维度的功能。 在接下来的九篇文章中,我将逐步介绍该平台的其他重要方面。
Apache Hudi从零到一:存储格式初探的更多相关文章
- Apache Hudi 设计与架构最强解读
感谢 Apache Hudi contributor:王祥虎 翻译&供稿. 欢迎关注微信公众号:ApacheHudi 本文将介绍Apache Hudi的基本概念.设计以及总体基础架构. 1.简 ...
- 使用Apache Hudi构建大规模、事务性数据湖
一个近期由Hudi PMC & Uber Senior Engineering Manager Nishith Agarwal分享的Talk 关于Nishith Agarwal更详细的介绍,主 ...
- Apache Hudi和Presto的前世今生
一篇由Apache Hudi PMC Bhavani Sudha Saktheeswaran和AWS Presto团队工程师Brandon Scheller分享Apache Hudi和Presto集成 ...
- 使用Apache Hudi + Amazon S3 + Amazon EMR + AWS DMS构建数据湖
1. 引入 数据湖使组织能够在更短的时间内利用多个源的数据,而不同角色用户可以以不同的方式协作和分析数据,从而实现更好.更快的决策.Amazon Simple Storage Service(amaz ...
- 在AWS Glue中使用Apache Hudi
1. Glue与Hudi简介 AWS Glue AWS Glue是Amazon Web Services(AWS)云平台推出的一款无服务器(Serverless)的大数据分析服务.对于不了解该产品的读 ...
- 基于Apache Hudi构建数据湖的典型应用场景介绍
1. 传统数据湖存在的问题与挑战 传统数据湖解决方案中,常用Hive来构建T+1级别的数据仓库,通过HDFS存储实现海量数据的存储与水平扩容,通过Hive实现元数据的管理以及数据操作的SQL化.虽然能 ...
- 基于Apache Hudi 的CDC数据入湖
作者:李少锋 文章目录: 一.CDC背景介绍 二.CDC数据入湖 三.Hudi核心设计 四.Hudi未来规划 1. CDC背景介绍 首先我们介绍什么是CDC?CDC的全称是Change data Ca ...
- 基于Apache Hudi在Google云构建数据湖平台
自从计算机出现以来,我们一直在尝试寻找计算机存储一些信息的方法,存储在计算机上的信息(也称为数据)有多种形式,数据变得如此重要,以至于信息现在已成为触手可及的商品.多年来数据以多种方式存储在计算机中, ...
- Apache Hudi 0.9.0版本重磅发布!更强大的流式数据湖平台
1. 重点特性 1.1 Spark SQL支持 0.9.0 添加了对使用 Spark SQL 的 DDL/DML 的支持,朝着使所有角色(非工程师.分析师等)更容易访问和操作 Hudi 迈出了一大步. ...
- Apache Hudi 介绍与应用
Apache Hudi Apache Hudi 在基于 HDFS/S3 数据存储之上,提供了两种流原语: 插入更新 增量拉取 一般来说,我们会将大量数据存储到HDFS/S3,新数据增量写入,而旧数据鲜 ...
随机推荐
- JS leetcode 拥有最多糖果的孩子 题解分析,六一快乐。
壹 ❀ 引 今天是六一儿童节,leetcode的每日一题也特别可爱,那么今天我们来解决一道与糖果有关的问题,题目来源1431. 拥有最多糖果的孩子,题目描述如下: 给你一个数组 candies 和一个 ...
- 基于OpenTelemetry实现Java微服务调用链跟踪
本文分享自华为云社区<基于OpenTelemetry实现Java微服务调用链跟踪>,作者: 可以交个朋友. 一 背景 随着业务的发展,所有的系统都会走向微服务化体系,微服务进行拆分后,服务 ...
- NC24755 [USACO 2010 Dec S]Apple Delivery
题目链接 题目 题目描述 Bessie has two crisp red apples to deliver to two of her friends in the herd. Of course ...
- 【Flink入门修炼】1-4 Flink 核心概念与架构
前面几篇文章带大家了解了 Flink 是什么.能做什么,本篇将带大家了解 Flink 究竟是如何完成这些的,Flink 本身架构是什么样的,让大家先对 Flink 有整体认知,便于后期理解. 一.Fl ...
- Vue 3 的 setup语法糖到底是什么东西?
前言 我们每天写vue3项目的时候都会使用setup语法糖,但是你有没有思考过下面几个问题.setup语法糖经过编译后是什么样子的?为什么在setup顶层定义的变量可以在template中可以直接使用 ...
- 项目实战:Qt编译Qt库以及使用C#调用Qt库,并实现C#集成Qt的tcp客户端
需求 1.Qt已经开发了应用,封装成Qt库,以供C#调用. 2.Qt的tcp客户端封装,以供C#调用,双向传递数据. 原理 1.使用QtCreator编译msvc版本的Qt库: 2.使 ...
- Flask学习(三)
数据库操作 数据库驱动(drivers)模块:pymysql.MySQLDB ORM ORM 全拼Object-Relation Mapping,中文意为 对象-关系映射.主要实现模型对象到关系数据库 ...
- 问题:django中对datetime类型数据在pycharm中sqlite3进行修改时,修改后datetime日期数据变成了时间戳类型
这是正在修改的 提交完之后 问题原因 问题原因是sqlite数据库对日期类型不敏感,Pycharm直接插入会变成图中这样的时间戳,用POST请求添加数据或Django自带的后台管理插入不会有这样的问题 ...
- CoaXPress 协议的CRC及其具体实现
CoaXPress CRC 在CXP协议中,CRC用在stream packet和control packet中,用于指示数据是否错误,如果是control packet, device发现CRC错误 ...
- 苹果工程师对iOS线程开发的那点事津津乐道
pthread,Thread总结 pthread: 通用的多线程API 使用方法 // 1. 创建线程: 定义一个pthread_t类型变量 pthread_t thread; // 2. 开启线程: ...