数据湖 Delta Lake、Hudi 与 Iceberg 详解 | 青训营笔记
这是我参与「第四届青训营 」笔记创作活动的的第13天
数据湖核心技术
文件结构
用户要求:
路径:
代码实现(json形式):
{
"schema":[
{
"name":"userID",
"type":"int"
},
{
"name":"date",
"type":"string"
},
{
"name":"event",
"type":"string"
},
{
"name":"phonenumber",
"type":"string"
}
],
"partition_col":"date",
"location":"mytable/",
"partition":[
"2020-01-01",
"2020-01-02"
]
}
Time travel
用户要求:
路径:
代码实现(json形式):
{
"schema":[
{
"name":"userID",
"type":"int"
},
{
"name":"date",
"type":"string"
},
{
"name":"event",
"type":"string"
},
{
"name":"phonenumber",
"type":"string"
}
],
"partition_col":"date",
"location":"mytable/",
"partition":[
{
"2020-01-01";[
"xxx.parquet" ,
"yyy.pqrquet"
],
"2020-01-02";[
"xxx.parquet" ,
"yyy.pqrquet"
]
}
]
}
Transaction
数据湖中的ACID:
- Atomicity:原子性-本次写入要么对用户可见,要么不可见
- Consistency:一致性-输入是说明,落盘就是什么
- Isolation:事务隔离-正确解决读写冲突和写写冲突
- Durability:持久性-落完数据后,即便服务器重启结果不变
用户要求:
路径:
实现:
- 写入流程:
- 写入 parquet 数据文件
- 写入 json 元数据文件
- 读写冲突(保证原子性):
- 用户只会读取以版本号数字命名的json文件,每次都读取到最大的版本号作为数据集的现状
- 新的写入写完parquet后开始写json文件,使用hash之对json文件命名,如a2fs4hfg8ee.json
- 直到json文件内容写入完毕,利用hdfs的renameIfAbsent能力将a2fs4hfg8ee.json替换为000006.json,到此commit完成,新的读取将会以000006.json作为最新版本
- 写写冲突:
- Update写入流程:
-
从最新的版本中,获取需要update的分区
-
乐观锁先把该写入的文件全落盘,然后写入json阶段
-
分以下两种情况
- 发现版本号和一开始没区别,直接写入新的版本
- 发现版本号增加了,看看新增的这些版本有没有更新我要更新的分区?
- 没有,直接写新的版本。
- 有,两者都更新了同一分区,需要重新update。
-
- Update写入流程: