数据湖三剑客:Delta Lake、Hudi 与 Iceberg 详解 | 青训营笔记
这是我参与「第四届青训营 -大数据场」笔记创作活动的第15天
一、发展历史
1. 数据湖发展阶段1 - Hadoop
1.1 优点
- 同一公司/组织可以使用共享存储
- 数据访问方便,灵活性高
1.2 缺点
- 没有记录文件的schema(包括列名、列类型),经常使用Schema on Query的方式
- 难以得知数据集包含了那些文件,是通过什么样的分区组织的
- 如果多个程序都在修改这个数据集(修改数据、修改表结构),其他程序难以配合做修改
2. 数据湖发展阶段2 - Hive
对数据湖的演进 - Hive Metastore
2.1 优点
-
对数据湖中的数据集进行集中“定义”
- 数据湖中存在了哪些数据集
- 它们都存储在什么目录
- 数据集的schema是什么样子的
- 数据集有哪些分区,每个分区的目录是什么
2.2 缺点
- 当A/B同时读分区/20220623下的文件,当Writer B重写分区时,Reader A和B读到的文件可能是不同的
- HIVE allows us to add column after last column only
3. 数据湖发展阶段3 - 湖仓一体
湖仓一体(数据湖的现状)∶
-
结合了数据湖和数据仓库的优势
-
将数据仓库中对于数据的严格管理直接实现到了低成本的分布式存储之上
-
Key Features:
- Transaction ACID
- Schema管理
- 存储计算分离
- 支持多种计算引擎和文件格式
4. 业界三大数据湖
Delta Lake、Hudi与Icebreg
5. 关于 “数据湖”
- 数据相关概念比较新,一直处在演进当中
- 一开始是HDFS,裸pb、txt日志等等,叫数据湖(管不动了就叫数据沼泽)
- 后来出现了了Iceberg、Hudi、Delta Lake了,数据湖概念就基本等于这些产品了
- 也更贴近与Lakehouse的概念
二、核心技术
1. 文件结构
写入数据湖时:
- 按照每条数据的date进行分区
- 额外使用metadata文件记录表信息
2. Time travel
要点
- 每次写入都生成一个新的元数据文件,记录变更
- 分区数据在Update时,不要删除旧数据,保证新旧共享
- 元数据中存储具体的文件路径,而不仅仅是分区文件
- 每一次写入操作,创建一个新的json文件,以递增版本号命名,记录本次新增/删除的文件
- 每当产生N个jsson,做一次聚合,记录完整的分区文件信息
- 用checkpoint记录上次做聚合的版本号
3. Transaction
- ACID:是指数据库在写入或更新资料的过程中,为保证事务是正确可靠的,所必须具备的四个特性。
- Atomicity:原子性--要么A-10 B+10,要么都不变
- Consistency:一致性--不可以A-10 B+5
- Isolation:事务隔离--A和C同时给B转10,B最终结果应是+20
- Durability:持久性--转账服务器重启,结果不变
3.1 原子性
3.1.1 写入流程
- 写入parquet 数据文件(data)
- 写入json元数据文件(metadata)
3.1.2 确保原子性
- 用户只会读取以版本号数字命名的json文件,每次都读取到最大的版本号作为数据集的现状
- 新的写入写完parquet后开始写json问价,使用hash值对json文件命名,如a2fs4hfg8ee.json
- 直到json文件内容写入完毕,利用hdfs的renameIfAbsent能力将a2fs4hfg8ee.json替换为000006.json,到此为止commit完成,新的读取将会以000006.json作为最新版本
3.2 事务隔离
Update写入流程:
-
从最新的版本中,获取需要update的分区
-
乐观锁先把该写入的文件全落盘,然后进入写json阶段
-
分几种情况:
-
发现版本号和一开始没区别,直接写信的版本;
-
发现版本号增加了,看看新增的这些版本有没有更新我要更新的分区
- 没有,直接写新的版本
- 有,两者都更新了同一分区,得重新update了
-
4. Schvema Evolution
ID将data和metadata的列名做一一对应
-
唯一确定的ID。新增列赋予新ID。删列ID不重复。
-
写入数据时,ID也写入数据文件
-
读取数据时,用ID做映射,如果:
- Data中没有,metadata中有有:add
- Data中有,metadata中没有:drop
- Data和metadata中都有同一ID,但是name不同:RENAME
- 如果都有同一列名,而ID不同?
三、各有所长
1. Iceberg 工作重点
用户体验
- Schema evolution
- Partion evolution
- Hidden partition
- Time Travel
- Version Rollback
性能
- 快速file plan
- 更多的filter方式
可靠性
- ACID Transaction
- 完全开源,由Apache孵化开发
1.1 well-designed Metadata Layer
- Metadata files定义了表结构,存储了snapshot信息,分区列信息等
- Manifest lists存储了一个snapshot中所有manifest的信息
- Manifests存储了一些data files的信息
- Data files就是具体的数据文件
1.2 Data File Filter
一些有助于filter 的数据被层层记录,比如:
- Manifest file记录了每个data file的分区范围
- Manifest list记录了每个manifest file的分区范围分区可以被快速定位!可以做manifest list 级别裁剪。
- Manifest file记录了每个data file每一列的最大值,最小值可以通过其他的列(Userld)做data file 级别裁剪。
1.3 Hidden Partition
传统的分区方式:
- 数据中包含了date列,则按照date分区;如果希望按照hour分区,则需要新增hour列
lceberg的分区方式:
-
动数据中包含timestamp列,设置好partition transform方式
- 设置为date时,iceberg帮你转化为date分区
- 设置为hour时,iceberg帮你转化为hour 分区
- lceberg记录了这层转化关系,并且按你的需要进行partition evolution
2. Hudi
Hudi 工作重点:
- Timeline service:Hudi管理transaction的方式
- Hudi Table Type:Copy on Write / Merge on Read
- 高效的Upserts:update or insert
- 索引表:快速定位一条数据的位置
- Streaming lngestion Service
- 完全开源,由Apache孵化
3. Delta Lake 工作重点
- ACID Transaction
- Schema校验(不是evolution)
- 流批一体
- Time Travel
- Upsert/Delete
- z-Order 优化
- 只开源了一部分,由Databricks自己主导开发,Z-order 等优化的实现未开源
四、总结场景
1. 三个数据湖的异同
2. 三个数据湖的热度
3. 技术选型
短期来看:每个项目都有一些属于自己的功能
- 如果强需求Upserts,也许Hudi是最好的选择
- D如果希望可扩展性强,那么设计优良的Iceberg是最好的选择
- 如果希望用上Z-Order等优化,那么掏钱买Databricks 的企业版 Delta是不二之选
长期来看:数据湖取代Hive,成为HDFS上的表格式标准是必然的,在选择之前问自己四个问题
- 我需要的feature在哪个数据湖上是最稳定的
- 哪一个数据湖能够用最简单的接入方式(SQL)用上最完善的功能
- 哪一个数据湖有计算引擎侧的支持和社区的支持
- 哪一个数据湖的版本管理做的最好,最鲁棒
4. 课程总结
- 数据湖的最新发展状态是湖仓一体
- 数据湖以低存储成本提供了ACID Transaction、Schema evolution、Time travel等高级功能