数据湖是一个存储了各种结构和非结构化数据的大规模数据存储系统,但在进行数据更新和增量处理时通常面临一些挑战。
Apache Hudi 的出现就是为了解决数据湖中的增量数据存储和数据更新问题。它支持将数据湖视为一个可更新的存储,允许在数据湖中执行增量更新和删除操作,同时保持数据一致性和可靠性。
一、什么是 Hudi
Apache Hudi 的全称是Apache Hadoop Upserts And Incrementals,是下一代流式数据湖平台,它将数据仓库和传统数据库的核心功能直接引入到了数据湖中。Hudi 提供了表、事务、高效的数据更新/删除、高级索引、流式数据集成服务、数据集群/压缩优化和高并发,并且支持多种开源的文件格式。
Hudi 不仅能胜任流式工作,还可以提供高效的增量批处理功能。Hudi 高效的性能可以支持很多查询引擎,比如:Apache Spark、 Flink、 Presto、 Trino、 Hive等等。
二、核心概念
1. Hudi Timeline
Timeline 展示了 Hudi 如何管理事务和其他表服务。
Hudi 的核心是维护不同时间对表执行的所有操作的事件表,这有助于提供表的即时视图,同时还有效的支持按到达顺序进行数据检索。
① Hudi 包含以下组件:
Instant action:在表上的操作类型
Instant time:操作开始的一个时间戳,该时间戳会按照开始时间顺序单调递增
state:即时状态
② Hudi 保证在时间轴上执行的操作都是原子性的,所有执行的操作包括:
commits:原子的写入一张表的操作
cleans:后台消除了表中的旧版本数据,即表中不在需要的数据
delta_commit:增量提交,将一批数据原子写入到MergeOnRead表中,并且只记录到增量日志中
compaction:后台协调 Hudi 中的差异数据
rollback:回滚,删除在写入过程中的数据
savepoint:将某些文件标记为
已保存,以便清理数据时不会删除它们,一般用于表的还原,可以将数据还原到某个时间点
③ 任何操作都可以处于以下状态:
Requested:表示已请求操作行为,但是尚未开始
Inflight:表示正在执行当前操作
Completed:表示已完成操作
2. Hudi File Layout
File Layout 展示了文件在 Hudi 中是如何存储的。
Hudi 将数据表组织成分布式文件系统上的目录结构,比如 HDFS
表可以被分成多个分区
在每个分区内,文件被组织成文件组,由文件 ID 唯一标识
每个文件组包含多个文件分片
每个文件分片包含基本文件和日志文件
Hudi采用 MVCC 设计,其中压缩操作将日志文件和基本数据文件合并成新的文件片,而清除操作则将未使用的文件分片去除。
3. Hudi Indexing
Hudi 通过使用索引机制,生成 hoodie 密钥映射对应文件 ID,从而提供高效 upsert 操作。
4. Hudi Table Types
Copy on Write:仅使用列式存储,例如 parquet。仅更新版本号,通过写入过程中执行同步合并来重写文件。支持 快照查询 和 增量查询。Merge on Read:基于列式存储(parquet)和行式存储(arvo)结合的文件进行存储。更新记录到增量文件,压缩同步和异步生成新版本的文件。支持 快照查询 、 增量查询 和 优化读查询。
5. Hudi Query Types
快照查询(Snapshot Queries):
查询操作将查询最新快照的表数据。如果是Merge on Read类型的表,它将动态合并最新文件版本的基本数据和增量数据用于显示查询。如果是Copy On Write类型的表,它直接查询parquet表,同时提供upsert/delete操作.增量查询(Incremental Queries):
查询只能看到写入表的新数据。这有效的提供了change streams来启用增量数据管道。优化读查询(Read Optimized Queries):
查询会看到给定提交/压缩操作时表的最新快照。
三、基础用例
1. 近实时摄取
将外部数据(例如事件日志,数据库,外部源)如何摄取到 Hadoop Data Lake 是一个众所周知的问题。在大多数 Hadoop 部署中,经常会以零碎的方式,使用多种摄取工具解决,这些数据对整个组织是最具有价值的。
对于 RDBMS 关系型的摄入,Hudi 提供了更快的 Upset 操作。例如,你可以通过 MySql binlog 的形式或者 Sqoop 导入到 hdfs 上的对应的 Hudi 表中,这样操作比 Sqoop 批量合并 job(Sqoop merge) 和复杂合并工作流更加快速高效。
对于 NoSql 的数据库,比如 Cassandra、Voldemort、Hbase,这种可以存储数十亿行的数据库。采用完全批量加载是根本不可行的,并且如果摄取数据要跟上通常较高的更新量,则需要更有效的方法。
即使对于像 Kafka 这样不可变数据库源,Hudi 也会在 HDFS 上强制执行最小文件大小,从而通过整体解决 Hadoop 领域中小文件过多问题,改善 NameNode 的运行状况。
对于事件流尤为重要,因为事件流通常较大(例如:点击流),并且如果管理不善,可能会严重损害 Hadoop 集群。
2. 近实时分析
通常,实时数据集市由专门的分析存储(例如 Druid 或 Memsql)提供支持,对于小规模的数据,可实现亚秒级响应查询。但是通常这些数据库最终会因为交互性较低的查询而被滥用,导致利用率不足。
另一方面,Hadoop 上交互式的 SQL 解决方案有 Presto 和 Spark sql。将数据的更新时间缩短至几分钟,Hudi 可以提供多种高效的替代方案,并可以对存储在 DFS 中的多个大小表进行实时分析,此外 Hudi 没有外部依赖,因此可以在不增加操作开销的情况下,进行更快更及时的分析。
3. 增量处理管道
Hadoop 提供的一项基本功能是,通过表示为工作流的 DAG 来构建彼此衍生的表链。工作流通常取决于多个上游工作流输出的新数据,一般来说,新数据的可用性由新的DFS文件夹/配置单元分区指示。举个例子:上游工作流U可以每小时创建一个Hive分区,并在每小时的末尾(processing_time)包含该小时(event_time)的数据,从而提供1小时的有效刷新。然后,下游工作流D在U完成后立即开始,并在接下来的一个小时内进行自己的处理,从而将有效延迟增加到2个小时。
4. 统一批处理和流处理
通过将流原语引入数据湖存储,Hudi 能够在几分钟内摄取数据,并创建比传统批处理快几个数量级的增量数据管道,从而开辟了新的可能性。与实时数据集市相比,通过将数据新鲜度缩短到几分钟,Hudi 可以为大量数据应用程序提供更有效的替代方案。此外,Hudi 没有前期服务器基础设施投资,因此可以对更新的分析进行更快的分析,而不会增加运营开销。
四、对比其他数据库
1. Kudu
Apache Kudu 是一个存储系统,其目标与 Hudi 类似,但 Hudi 的目标是通过对 Upserts 的一流支持,对 PB 级数据进行实时分析。
一个关键的区别是 Kudu 还试图充当 OLTP 的数据存储,而 Hudi 并不希望这样做。因此,Kudu 不支持增量拉取,Hudi 这样做是为了启用增量处理。
Hudi 旨在与底层 Hadoop 兼容文件系统一起使用,并且没有自己的存储服务器;而Kudu则需要硬件和操作支持。
2. Hbase
HBase 是 OLTP 的 key/value 存储,但鉴于与 Hadoop 的相似性,用户通常倾向于将 HBase 与分析相关联。鉴于 HBase 经过严格的写优化,它支持开箱即用的亚秒级更新,Hive-on-HBase 允许用户查询该数据。Hudi 弥补了更快的数据与具有分析性存储格式之间的差距。从操作的角度来看,与管理分析用的大型 HBase Region Server 相比,为用户提供可提供更快数据的库更具可扩展性。HBase 不像 Hudi 这样的一等公民来支持诸如 commit timeline,increment pull 之类的增量处理原语。