Apache Hudi数据湖存储格式介绍
Apache Hudi数据湖存储格式介绍
总览
在企业信息化的过程中,随着信息化工具的升级和新工具的应用,数据量变得越来越大,数据格式越来越多,决策要求越来越苛刻,数据仓库技术也在不停的发展。数据仓库是伴随着企业信息化发展起来的,从1990年 Inmon 提出数据仓库概念到今天,其架构经历了最初的经典数仓架构、离线数仓架构、Lambda 架构、Kappa 架构、混合架构、实时数仓以及数据湖。
在数据湖出现之前,单一的数仓架构往往很难兼顾数据时效性、数据持久化与数据探索。以Apache Hive构建的离线数仓为例,由于其架构限制,往往只能够实现T+1的数据新鲜度;而对于基于消息队列与实时引擎构建的实时数仓,由于其存储在消息队列中,如需进行深入的数据探索,往往还需要将其持久化到离线数仓中进行分析。
以Apache Hudi(下文统一称为Hudi)为代表的数据湖解决了现有数仓架构的根本性问题,在数据新鲜度和数据持久化实现了权衡。从本质上来说,Hudi是一种表格式(Table Format),其本身是无状态的,仅提供接口供Flink或者Spark等引擎实现数据写入。
从Apache Parquet看Apache Hudi的存储格式
Parquet文件格式
从Apache Parquet(下文统一称为Parquet)文件格式入手,或许让我们能够更好了解Hudi的存储格式。以Hive为例,我们在建表时可以指定数据存储格式以及是否添加压缩支持,而当我们指定数据存储格式为Parquet时,其意味着该表的数据存储在一系列以parquet结尾的文件系统中。Parquet格式文件不同于文本文件,其本身有一定的组织方式,具体如下图所示:
Parquet文件将数据按照列式存储,但并不是说在整个文件中一个列的数据都集中存储在一起,而是划分了Row Group、Column Chunk以及Page的概念。如下所述:
- Parquet文件会划分为很多Row Group。每个Row Group会存储一个表中相连的多行数据。
- 每个Row Group会分成多个Column Chunk。多行数据会按照列进行划分,每列的数据集中存储于一个Column Chunk中,因为每个列的数据类型不同,因此不同的Column Chunk会使用不同算法进行压缩\解压缩。
- 每个Column Chunk会分为多个Page。
具体来说,其数据组织方式可由下图组成。
一旦我们对Parquet有一些了解之后就会发现,Parquet实际上就是一系列jar包,这些jar包提供了相关的读取和写入API,上层计算引擎只需要调用对应的API就可以将数据写成Parquet格式的文件,这个jar包里面实现了如何将复杂类型的数据进行处理,如何按照列式存储构建一个Page,再构建一个Column Chunk,再接着构建一个Row Group,最后构建元数据统计信息后形成一个Parqeut文件。相反,调用扫描API,这个jar包实现了如果通过元数据统计信息定位扫描的起始位置,如何按照文件格式正确高效地解压数据块将数据扫描出来。
所以,一个Parquet文件格式实际上包含了数据schema定义(是否支持复杂数据类型),数据在文件中的组织形式,文件统计信息、索引以及读写的API实现。
Hudi表格式
Hudi的表格式(table format)的组织方式与Parquet的文件组织方式的逻辑类似,其存储由元数据、索引以及原始数据三部分组成。元数据是hudi表的schema、对表执行的所有操作的记录等信息;索引表示将给定的hoodie键(记录键+分区路径)一致地映射到一个文件id;而原始数据则是以parquet或者avro格式存储的具体数据。对于原始数据,在一个分区Hudi表中,分区内的数据由一系列文件组(File Group)组成,文件组由一系列文件片(File Slice)组成,而文件片则表示一系列基础数据文件。相应地,Hudi也提供了一系列API实现Hudi表的读写、索引等操作。
Hudi功能特性
但相对于Parquet来说,Hudi是更加复杂且具有更多特点的。Hudi 表由 Timeline 和 File Group两大项构成。Timeline 由一个个 commit 构成,一次写入过程对应时间线中的一个 commit,记录本次写入修改的文件。基于Spark或者Flink引擎,支持在HDFS、OSS等底层存储上实现插入更新和增量读取的流语义,其具有如下特点:
- 支持ACID
- 支持SnapShot数据隔离,保证数据读取完整性,实现读写并发能力
- 数据commit,数据入湖秒级可见
- 快速Upsert能力
- 支持可插拔索引进制实现新增更新数据快速入湖
- 扩展Merge操作,实现新增、更新、删除混合数据同时入湖
- 支持写入同步小文件合并能力,写入数据自动按照预设文件大小进行文件合并
- Schema Evolution
- 支持湖内数据schema的同步演进
- 支持多种常见schema变更操作
- 多种视图读取接口
- 支持实时快照数据读取方式
- 支持历史快照数据读取方式
- 支持当前增量和历史增量数据读取方式
- 支持快速数据探索分析
- 多版本控制
- 数据按照提交版本存储,保留历史操作记录,方便数据回溯
- 数据回退操作简单,速度快
Hudi典型应用场景
Hudi的快速更新和增量读取能力使其能够完全胜任实时数仓的能力。通过CDC工具将MySQL、PostgreSQL或者ORACLE数据库的增量数据更新到Kafka后,通过Spark Streaming或者Flink将数据实时入湖落盘时,给下游提供分钟级可见的数据新鲜度。
在最新release-0.12版本中,Hudi支持通过Hive Metastore实现表元数据信息管理,进而通过Flink或Spark引擎写入,Flink、Spark、Presto、Trino、Hive等引擎的读取,实现了湖仓架构的结合。
总结
在数据摄取方面,Hudi可实现实时增量更新,快速进行数据的新增、更新以及删除操作;而在读取方面,Hudi则是提供了快照视图、读优化试图以及增量视图。而基于HMS Catalog,Hudi可直接与Hive数仓结合,构建统一的批流一体湖仓架构。