Apache Hudi将核心仓库和数据库功能直接带到数据湖中。Hudi提供了表、事务、高效upserts/删除、高级索引、流式摄取服务、数据群集/压缩优化以及并发,同时保持数据以开源文件格式保留。
Hudi是Hadoop Upserts and Incrementals
缩写,用于管理分布式文件系统DFS上大型分析数据集存储。
Hudi是一种针对分析型业务的、扫描优化的数据存储抽象,它能够使DFS数据集在分钟级的时延内支持变更,也支持下游系统对这个数据集的增量处理。
Apache Hudi支持在Hadoop兼容的存储之上存储大量数据,不仅可以批处理,还可以在数据湖上进行流处理。
在Hudi中维护一个所有操作的时间轴,每个操作对应时间上面的instant,每个instant提供表的view,同时支持按照时间顺序搜索数据。
Instant action
: 对表的具体操作。Instant time
: 当前操作执行的时间戳。state
:当前instant的状态。Hudi 能够保证所有的操作都是原子性的,按照时间轴的。Hudi的关键操作包含:
COMMITS
:一次原子性写入数据到Hudi的操作。CLEANS
:删除表中不再需要的旧版本文件的后台活动。DELTA_COMMIT
: delta commit
主要是一批原子性写入MOR表,其中部分或者全部都会写入delta logs。COMPACTION
: 在后台将不同操作类型进行压缩,将log文件压缩为列式存储格式。ROLLBACK
: 将不成功的commit/delta commit
进行回滚。SAVEPOINT
: 将某些文件标记为已保存,方便异常场景下恢复。State详细解释:
REQUESTED
: 表示已计划但尚未启动操作INFLIGHT
: 表示当前正在执行操作COMPLETED
: 表示在时间线上完成一项操作Hudi采用多版本并发控制(MVCC),其中压缩操作合并日志和基本文件以生成新的文件切片,而清理操作清除未使用/旧的 文件切片以回收文件系统上的空间。
表类型 | 支持查询类型 |
---|---|
Copy On Write | 快照查询 + 增量查询 |
Merge On Read | 快照查询 + 增量查询 + 读取优化查询 |
使用排他列式文件格式(比如:parquet)存储,简单地更新版本&通过在写入期间执行同步合并来重写文件。
下面从概念上说明了这是如何工作的,当数据写入写时复制表和在其上运行的两个查询时。
在写入数据时,对现有文件组的更新会为该文件组生成一个带有提交即时时间戳的新切片,而插入会分配一个新文件组并为该文件组写入其第一个切片。上面红色标出来的就是新提交的。
使用列式(比如:parquet) + 基于行的文件格式 (比如:avro) 组合存储数据。更新记录到增量文件中,然后压缩以同步或 异步生成新版本的柱状文件。
将每个文件组的传入追加存储到基于行的增量日志中,以通过在查询期间将增量日志动态应用到每个文件id的最新版本来支持快照查询。 因此,这种表类型试图均衡读取和写入放大,以提供接近实时的数据。
对比维度 | CopyOnWrite | MergeOnRead |
---|---|---|
数据延迟 | Higher | Lower |
查询延迟 | Lower | Higher |
更新成本(I/O) | Higher(需要重写parquet) | Lower(添加到delta log) |
Parquet文件大小 | Smaller(高更新(I/O)成本) | Larger(低更新成本) |
写入放大 | Higher | Lower(取决于压缩策略) |
Hudi 通过索引机制将给定的 hoodie key(record key + 分区路径)映射到文件id,从而提供高效的更新插入。 一旦record的第一个版本写入文件,record 的key和文件ID 之间的映射就不会改变。
对于COW表来讲: 可以避免扫描整个文件系统,达到支持快速upsert/delete操作。
对于MOR表来讲: 允许限制base文件中需要合并的records的数量。对于一个base文件只需要根据当前base文件的record的跟新等进行合并。
Comparion cost对比:
Hudi支持的索引如下:
名称 | 备注 |
---|---|
Bloom索引 | 采用根据记录key构建的布隆过滤器,还可以选择使用记录key范围修剪候选文件。 |
GLOBAL_BLOOM索引 | 与Boolm索引类似,但是作用范围是全局 |
Simple索引 | 针对从存储上的表中提取的键对传入的更新/删除记录执行精益联接。 |
GLOBAL_SIMPLE索引 | 与Simple类似,但是作用范围是全局 |
HBase索引 | 将index信息保存到Hbase当中。 |
INMEMORY索引 | 在Spark、Java程序、Flink的内存中保存索引信息,Flink和Java默认使用当前索引 |
BUCKET索引 | 使用桶hash的方式定位文件组,在大数据量情况下效果较好。可以通过hoodie.index.bucket.engine指定bucket引擎。 |
RECORD_INDEX索引 | 索引将record的key保存到 Hudi元数据表中的位置映射。 |
自定义索引 | 自定义实现的索引。 |
BUCKET索:
Hudi 表的数据文件一般使用 HDFS 进行存储。从文件路径和类型来讲,Hudi表的存储文件分为两类。