第一部分 知识准备
⼤家在学习hudi的时候,上⾯这张图⼀定是最先看到的,也是看到最多的,但是每次看到这张图,相信⼤家都有共同的疑问:TimeLine是啥?Commit是啥?这些东⻄结合在⼀起如何实现hudi的准实时查询,如何实现HUDI的CRUD语义,本篇⽂章我们以Spark On Hudi为例,通过分析Spark On Hudi的 UpSert流程,深⼊理解Hudi的内部机制。
⼀、什么是TimeLine
个⼈理解TimeLine是将⽤户感兴趣的,针对对Hudi表的变更操作,从时间维度上连接起来,⽤户可以通过timeline找到某个时间范围内⾃⼰感兴趣操作的元数据,⽐如数据的增加/修改/删除,或者由Hudi后台运⾏的clean/compact/clustering操作。所以TimeLine是由⼀些在时间维度上有先后关系的,对hudi表有更新的操作的元数据的集合,在hudi的源码中可以随处看到创建TimeLine的操作,⽐如
以上代码就是将hudi表未完成的Compact操作过滤出来,并创建新的TimeLine 。
TimeLine主要由instances、details和metaClient组成
(⼀)instances就是对hudi表操作的集合,TimeLine会扫描hudi表的.hoodie路径下的拥有合法扩展名的所有⽂件,并创建对应的HoodieInstance,最后加⼊到instances集合
HoodieInstance就是某个时间点对hoodie表的修改操作,每个HoodieInstance都有针对的操作以及所属的状态
HoodieInstance常⻅的操作有:commit、deltacommit、clean、rollback、compaction
HoodieInstance对应的状态有:REQUESTED、INFLIGHT、COMPLETED、INVALID
不同的操作以及状态的组合对应了不同的instance⽂件名,如下:
(⼆)details是⼀个函数成员,定义了怎么从给定的instance中读取元数据内容
(三)metaClient⽤于获取元数据位于的⽂件系统以及路径
⼆、表存储结构
下⾯我们来梳理下hudi中与表存储结构相关的概念:Partition、FileGroup、FileID、Slice、BaseFile、
LogFile等概念:
(⼀)hudi表根据partition进⾏分区,和所有流⾏的OLAP查询引擎数据存储⽅式⼀样,根据分区减少
数据的访问量
(⼆)partition下以⽂件的形式保存了hudi表数据,不同表类型保存的⽂件形式不⼀样。⼀个分区下的
数据⼀般需要分为若⼲⽂件(和Hive⼀样)。
(三)COW表数据在BaseFile中,⽽MOR表在BaseFile和LogFile⽂件中
实际的⽣产环境如图所示
(四)为了⽀持Hudi表的修改操作,⽂件有不同的版本,每个版本称为slice,⼀个⽂件所有的slice(版本)组合起来就是⼀个FileGroup。
总结⼀下,⼀个hudi表由不同的partition组成,⼀个partition中的数据分散在不同的FileGroup中,FileGroup通过FileGroupID标识,FileGroupID由partitionPath以及FileID组成。FileGroup由不同的slice组成,slice表示不同时间提交的数据版本,COW的slice由BaseFile组成,MOR的slice由
BaseFile+LogFile组成,⼀个FileGroup下的slice拥有相同的FileId,通过FileId+instanceTime可以定位到⼀个具体的BaseFile或者FileGroup。
Copy On Write表
接下来我们再把这些概念串起来,看看不同表类型upsert的整体流程