欢迎关注微信公众号:ApacheHudi
1. 项目背景
传统数仓的组织架构是针对离线数据的OLAP(联机事务分析)需求设计的,常用的导入数据方式为采用sqoop或spark定时作业逐批将业务库数据导入数仓。随着数据分析对实时性要求的不断提高,按小时、甚至分钟级的数据同步越来越普遍。由此展开了基于spark/flink流处理机制的(准)实时同步系统的开发。
然而实时同步数仓从一开始就面临如下几个挑战:小文件问题。不论是spark的microbatch模式,还是flink的逐条处理模式,每次写入HDFS时都是几M甚至几十KB的文件。长时间下来产生的大量小文件,会对HDFS namenode产生巨大的压力。
对update操作的支持。HDFS系统本身不支持数据的修改,无法实现同步过程中对记录进行修改。
事务性。不论是追加数据还是修改数据,如何保证事务性。即数据只在流处理程序commit操作时一次性写入HDFS,当程序rollback时,已写入或部分写入的数据能随之删除。
Hudi是针对以上问题的解决方案之一。以下是对Hudi的简单介绍,主要内容翻译自官网。
2. Hudi简介
2.1 时间线(Timeline)
Hudi内部按照操作时刻(instant)对表的所有操作维护了一条时间线,由此可以提供表在某一时刻的视图,还能够高效的提取出延后到达的数据。每一个时刻包含:时刻行为:对表操作的类型,包含:commit:提交,将批次的数据原子性的写入表;
clean: 清除,后台作业,不断清除不需要的旧得版本的数据;
delta_commit:delta 提交是将批次记录原子性的写入MergeOnRead表中,数据写入的目的地是delta日志文件;
compacttion:压缩,后台作业,将不同结构的数据,例如记录更新操作的行式存储的日志文件合并到列式存储的文件中。压缩本身是一个特殊的commit操作;
rollback:回滚,一些不成功时,删除所有部分写入的文件;
savepoint:保存点,标志某些文件组为“保存的“,这样cleaner就不会删除这些文件;时刻时间:操作开始的时间戳;
状态:时刻的当前状态,包含:requested 某个操作被安排执行,但尚未初始化
inflight 某个操作正在执行
completed 某一个操作在时间线上已经完成
Hudi保证按照时间线执行的操作按照时刻时间具有原子性及时间线一致性。
2.2 文件管理
Hudi表存在在DFS系统的 base path(用户写入Hudi时自定义) 目录下,在该目录下被分成不同的分区。每一个分区以 partition path 作为唯一的标识,组织形式与Hive相同。
每一个分区内,文件通过唯一的 FileId 文件id 划分到 FileGroup 文件组。每一个FileGroup包含多个 FileSlice 文件切片,每一个切片包含一个由commit或compaction操作形成的base