使用场景
Apache Hudi 是一个功能强大的数据湖仓平台,凭借其高性能设计、丰富的功能集以及面向现代数据工程需求的独特优势,在各种用例中表现出色。本文档将探讨其核心用例与差异化特性,帮助你理解在何时、为何 Hudi 是数据湖仓的优秀选择。
流式/CDC 数据摄入到数据湖仓
Hudi 擅长处理增量数据更新,是 CDC 管道的理想选择。这类管道将 MySQL 或 PostgresSQL 等上游数据库中频繁的更新、插入和删除,复制到下游数据湖仓表中。数据湖中的这层"原始数据"往往构成了后续从 BI 到 AI 的所有数据工作的基础。虽然将事件日志、数据库、外部来源等 OLTP 源的数据摄入到数据湖是一个重要问题,但遗憾的是,它常常被以零敲碎打的方式解决,需要混用各种各样的摄入工具。
为什么选择 Hudi?
- 独特的设计选择,如 Merge-On-Read 表、记录级索引和异步压缩,能够快速高效地吸收表变更,接近理论最优水平。
- 内置了面向 Spark、Flink 和 Kafka Connect 的摄入工具,只需一条命令即可完成数据摄入。
- 支持从流式数据源(Kafka、Pulsar 等)、云存储(S3、GCS、ADLS 等)乃至 JDBC 进行增量摄入,并自动管理检查点。
- 支持广泛使用的数据格式(Protobuf、Avro、JSON)、文件格式(parquet、orc、avro 等)以及 Debezium 等变更日志格式。
- 即使是针对海量仅追加流式数据的可扩展去重,也能通过布隆过滤器索引和区间树等高级数据结构实现高效的范围裁剪。
- 与主流 Schema 注册中心集成,能够在源系统 Schema 变化时自动、安全地在线演进表结构。
- Hudi 通过 RecordPayload/RecordMerger API 支持流式工作负载的事件时间排序和迟到数据处理,除了"最新写入者胜出"语义外,还允许你按照数据库 LSN 顺序合并更新。如果没有这项能力,当输入记录乱序或迟到(这在现实中不可避免地会发生)时,表可能会在(事件)时间上发生回退。
将负载从昂贵的数据仓库中卸载
随着组织规模的扩大,传统的 ETL 操作和数据仓库中的数据存储成本会变得异常高昂。Hudi 提供了一种高效的方式,将这些工作负载迁移到数据湖仓中,在不牺牲性能的前提下显著降低成本。
为什么选择 Hudi?
Hudi 让你可以使用开放的数据格式将数据存储在自己的云账户或存储系统中,避免厂商锁定,也避免厂商收取额外的存储费用。这还能让你把数据开放给其他计算引擎,包括 Presto、Trino、Starrocks 等众多开源查询引擎。
像 hudi-dbt 这样的适配器插件,可以轻松地将现有的 SQL ETL 管道迁移到 Apache Spark SQL。用户随后可以利用 Hudi 快速、高效的写入性能,降低 ETL 管道中 'L'(加载)的成本。
Hudi 的存储格式经过优化,可以高效计算表上两个时间点之间的"差异",从而通过消除对大型事实表的高成本扫描,实现大型 SQL 连接的高效改写。这降低了 ETL 管道中 'E'(抽取)的成本。
此外,Hudi 提供了一套功能完备的表服务,能够在后台自动对数据进行优化、分簇和合并,相比使用数据仓库的专有计算服务,可显著节约成本。
Hudi 与 Flink 等流处理引擎以及 Dynamic Tables 结合使用,可以帮助取代缓慢且昂贵的仓库 ETL 流程,同时还能大幅提升数据的时效性。
高性能开放表格式
过去几年中,数据仓库呈现出一种日益增长的趋势,即在"开放表格式"层之上支持读写操作。表格式由一个或多个开放文件格式、描述这些文件如何构成表的元数据,以及一套用于并发读写此类表的协议组成。虽然 Hudi 所提供的能力不止于这样一个表格式层,但它内嵌了一个强大的原生开放表格式,即便面对全球规模最大的表也能实现高性能。
为什么选择 Hudi?
Hudi 格式将元数据同时存储在事件日志(时间线)和快照表示(元数据表)中,从而在保留大量表版本时仅产生极小的存储开销,同时仍能为规划快照查询提供快速的访问能力。
表的元数据还以索引方式存储,便于进行高效查询处理。例如,列和分区的统计信息采用类似 SSTable 的文件格式存储,以确保仅读取与查询所涉及列相关的少量元数据。
Hudi 从底层设计之初就引入了索引组件,以少量增加存储开销为代价,提升写入和查询性能。目前提供了基于哈希的记录索引、布隆过滤器索引等多种索引,未来还将有更多索引加入。
在并发控制(CC)方面,Hudi 将写入者、读取者以及维护表的表服务谨慎地视为彼此独立的实体。这一设计使 Hudi 能够在写入者与压缩/索引任务之间实现多版本并发控制(MVCC),让写入者可以安全地执行写入,而无需因冲突而被阻塞或重试——在其他方案中,这类重试会浪费大量计算资源。
在两个写入者之间,Hudi 采用乐观并发控制(OCC),基于提交时间顺序提供写入完成时的可串行化保证,并引入了一种新型的非阻塞并发控制(NBCC),基于事件时间进行记录合并(事件时间处理)。
得益于上述设计选择,以及通过 Apache XTable 与其他表格式实现的互操作性,Hudi 表常常是 Delta Lake 或 Apache Iceberg 等其他表格式背后最快的支撑表。
开放数据平台
许多组织都希望构建一个开放、面向未来且可扩展的数据平台。这需要提供数据格式、API 和数据计算服务的开源组件,并能够将它们自由组合搭配,以搭建整个平台。这样的开放平台对于组织利用最新的技术和工具也至关重要,使其不必受制于某一家厂商的路线图。
为什么选择 Hudi?
Hudi 仅在开放的数据、文件和表格式上进行操作。Hudi 不绑定于任何特定的数据格式或存储系统。
开放的数据格式固然有帮助,但 Hudi 还通过提供开放的计算服务来实现完全的自由,这些服务涵盖数据的摄取、优化、索引和查询。例如,Hudi 的写入器自带自我管理的表服务运行时,可在每次写入后于后台自动维护表。通常情况下,Hudi 加上你喜爱的开源查询引擎,就足以搭建并运行一个开放的数据平台。
便于实现性能优化或管理的开放服务示例包括:自动文件大小调整用于解决"小文件"问题、聚簇用于将相关数据存放在一起、压缩用于调优低延迟摄取与快速读查询、索引用于实现更快的写入/查询、多维分区(Z-Order)、通过标记机制自动清理未提交数据、以及自动清理用于自动删除文件的旧版本。
Hudi 提供了丰富的选项,用于高效地预排序/预加载数据,并继之以丰富的数据聚簇技术,以管理表内的文件大小和数据分布。在每种情况下,Hudi 都提供了高度可配置的能力,用于确定这些服务何时、以何种频率被调度、规划和执行。例如,Hudi 内置了若干用于压缩和聚簇的常见规划策略。
除了兼容 Apache Iceberg、Delta Lake 等其他开放表格式,以及支持与各类数据目录的目录同步服务之外,Hudi 是构建数据基础最开放的选择之一。
借助增量处理构建高效的数据湖
组织约有 50% 的预算花费在数据管道上,用于转换和准备数据以供消费。随着数据量的增长,运行这些管道的成本也随之上升。Hudi 拥有一组独特的功能组合,通过引入数据增量处理的新范式,使其成为数据管道的高效选择。当前最先进的做法要求为数据处理配备两套完全不同的数据栈。批处理栈将数据以文件/对象的形式存储在本地或云端存储上,由 Spark、Hive 等引擎处理。而流处理栈则将数据以事件的形式存储在 Kafka 等独立的存储系统中,由 Flink 等引擎处理。即使处理引擎为这两种数据处理风格提供了统一的 API,底层存储的差异仍使得无法用一套栈来完成另一套栈的工作。Hudi 提供了一个统一的数据湖仓栈,可同时用于批处理和流处理模型。
Hudi 引入了「增量处理」,将流处理模型(即每隔 X 秒/分钟只处理新增或变更的数据)应用于批处理存储(即基于开放数据格式构建的云端数据湖仓)之上,兼顾了两者的优点。增量处理要求能够通过索引快速将变更写入表中,同时还要让数据可以被高效查询。另一项要求是,能够高效计算出表在两个时间点之间的精确变更集合,使管道每次运行时只需高效处理新数据,而无需扫描整张表。如果想了解更多,可以在这里找到关于增量处理优势的详细说明。
为什么选择 Hudi?
- 通过将流处理原语引入数据湖存储,Hudi 能够在几分钟内完成数据摄入与处理,从而开启新的可能性,并消除对专用实时分析系统的需求。
- Hudi 将记录组织为文件组(file group),更新操作关联到同一个文件组,从而限制查询需要扫描的数据量,即对于某个基础文件,只需扫描同一文件组内的日志文件。
- Hudi 添加了低开销的记录级元数据以及元数据的补充日志,用于计算 CDC 变更流,以便在写入和后台表服务操作不断发生的情况下,追踪某条变更在表中的变化与迁移过程。例如,即使由于分片聚类(clustering)导致许多小文件被合并到另一个文件中,Hudi 仍能保留变更历史,且不依赖于表快照的维护方式。在基于快照的元数据追踪方案中,仅仅过期一个快照就可能导致变更历史丢失。
- Hudi 可以原生编码更新,而不必被迫将其转化为删除加插入操作——后者往往会导致记录在文件之间持续随机重新分布,降低数据跳过(data skipping)的效率。Hudi 将某次删除或更新关联到该记录最初插入时所在的文件组(或最近一次聚类后所在的文件组),从而保留聚类数据的空间局部性或记录插入的时间顺序。因此,基于时间进行过滤的查询(例如按时间窗口查询事件/日志)可以高效地仅扫描少数文件组即可返回结果。
- 在此基础上,Hudi 还支持部分更新编码,能够将部分更新高效地编码到增量日志中。对于列式数据而言,这意味着写入/合并的成本与合并/更新语句中的列数成正比。
- MoR(Merge on Read,读时合并)的核心思路是通过写入增量日志(Hudi)和位置删除文件(Iceberg)来降低写入成本与延迟。Hudi 采用约 4 种索引方式,快速定位被更新记录所属的文件。依赖全表扫描的格式很快就会在写入性能上遇到瓶颈,例如每 5-10 分钟向一个 1TB 的表中更新 1GB 数据的场景。
- 在大量采用 MoR 的流式工作负载中,Hudi 是唯一原生支持事件时间排序和迟到数据处理的湖仓存储系统。
AI 原生数据湖仓
大语言模型(LLM)和多模态 AI 的兴起引发了一场根本性的范式转变,使数据湖仓的主要工作负载从传统的 ETL/BI 分析转向特征工程、模型训练和检索增强生成(RAG)。传统的数据湖仓在设计之初便以结构化的表格数据为核心,导致现代 AI 应用在其中显得格格不入、支离破碎。这些高级工作负载需要无缝地将结构化元数据与海量爆发的高维向量嵌入、原始非结构化二进制对象(如图像、文本、音频和视频)以及高度动态的半结构化负载(如模型配置和 LLM 响应输出)结合在一起。
在这种多模态现实中,工程团队往往不得不维护彼此割裂、各自为政的基础设施。原始二进制文件被存放在无人管理的对象存储中,而向量嵌入则被同步到独立的外部向量数据库中。这种碎片化的架构带来了严重的"同步困境":它会产生多份数据副本,推高运维基础设施成本,缺乏实时响应能力,并且完全破坏了整个 AI 生命周期中的事务一致性。例如,模型训练或 RAG 工作流要求严格的数据血缘、时点可复现性和版本控制。如果某个嵌入更新了,但与之对应的原始图像或元数据没有随之原子性地提交,下游模型就会受到过期或不匹配数据的影响。AI 原生的数据湖仓将结构化、半结构化和非结构化数据统一到单一的事务性存储层中,从而消除了这些写入扩展瓶颈和事务不一致问题。
Apache Hudi 通过在同一表结构中支持多模态数据类型,提供了 AI 原生的湖仓架构。大型二进制对象(BLOB)、稠密语义向量(VECTOR)以及灵活的半结构化载荷(VARIANT)都原生存储在同一 Hudi 数据文件中。由于多模态数据被管理在同一个湖仓内,而非分散在各自的基础设施中,非结构化数据同样可以继承 Hudi 基于时间线的 ACID 事务、表结构演进以及时间旅行查询能力。Hudi 的表服务、文件大小调整、清理、压缩和聚簇会在包含这些数据类型的表上运行,以优化面向相似性检索(hudi_vector_search)和 BLOB 读取(read_blob())的数据布局。
下表是使用 Hudi 中 AI 原生数据类型的技术入口:
| 类型 | 声明方式 | 写入 | 读取 |
|---|---|---|---|
VECTOR | DDL | SQL DML · DataFrame | hudi_vector_search TVF |
BLOB | DDL | SQL DML · DataFrame | read_blob() |
VARIANT | DDL | SQL DML · DataFrame | 查询 VARIANT |
| Lance 文件格式 | TBLPROPERTIES | DataFrame | (透明;仅支持 Spark) |
如需查看涵盖图像嵌入、原始字节和相似度搜索的完整示例,请参阅非结构化数据快速入门指南。
| 用例 | 类型与特性 |
|---|---|
| 图像 / 视频搜索 | VECTOR 向量嵌入 + BLOB 原始帧 + hudi_vector_search |
| 检索增强生成(RAG) | 检索 VECTOR 分块嵌入以组装 LLM 上下文 |
| LLM 输出管理 | VARIANT 存储响应负载 + VECTOR 进行语义索引 |
| 推荐系统 | 通过 VECTOR 相似度实现协同过滤;借助增量查询实现增量式重新嵌入 |
| 内容审核 | BLOB 原始内容 + VECTOR 内容嵌入 + 增量处理 |
| 多模态分析 | 结构化元数据 + VECTOR 嵌入 + BLOB 原始数据,统一存于一张表中 |
| 机器学习特征库 | VECTOR 存储特征嵌入,VARIANT 存储稀疏特征映射;通过时间旅行实现时间点检索 |
| 实验跟踪 | VARIANT 存储异构的模型配置与指标;通过增量查询获取最新运行结果 |
| 数据标注流水线 | BLOB 存储原始数据,增量查询获取未标注数据,事务化更新标注结果 |
为什么 AI 工作负载选择 Hudi
- 跨模态统一存储:原始二进制对象(
BLOB)、语义向量嵌入(VECTOR)、半结构化负载(VARIANT)以及标准分析列共同存放于同一张 Hudi 表中,共享同一时间线、schema 演进机制和访问控制。 - 增量嵌入管道:Hudi 的增量查询让特征管道只需对自某次提交以来发生变化的行重新进行嵌入,而不必重新处理整个批次。
- 多模态事务保证:向量更新、二进制变更和元数据修改以原子方式提交。将
VECTOR列与BLOB列连接的相似性查询,绝不会观察到嵌入引用了已删除或已过期二进制资产的状态。 - 自动化的表服务:文件大小整理、清理、压缩和聚簇均适用于包含
VECTOR、BLOB和VARIANT列的表。 - 开放的多引擎访问:Hudi 表可由 Apache Spark 和 Apache Flink 写入与读取,也可由即将推出的原生 Python / Rust 客户端(hudi-rs)直接读取底层 Parquet 表示。
评论
登录后参与评论
KnowForge