这是我参与「第四届青训营」笔记创作活动的第12天。
知识点小记
数据湖发展历史
Hadoop
数据湖的最开始的概念——分布式存储HDFS,适用目录来区分不同的数据集。 好处:同一公司可以使用共享存储,数据访问方便,灵活性高。
坏处:没有记录文件的schema,经常使用Schema on Query的方式。难以得知数据集包含了哪些文件,是通过什么样的分区组织的。如果多个程序都在修改这个数据集,其他程序难以配合做修改。
Hive
好处:对数据湖中的数据集进行集中的定义,定义了数据湖中存在了哪些数据集、他们都存储在什么目录、数据集的schema是什么样子的、数据集有哪些分区以及分区的目录信息。
问题:需要Transaction ACID,需要支持更多的schema变更。
湖仓一体
结合了数据湖和数据仓库的优势,将数据仓库中对于数据的严格管理直接实现到了低成本的分布式存储之上。
关键特点:
- Transaction ACID
- Schema 管理
- 存储计算分离
- 支持多种计算引擎和文件格式
核心技术
文件结构
按照每条数据的date进行分区,使用metadata文件记录表信息,如下图中的json格式的文件。
Time travel
其要点在于每次写入都生成一个新的元数据文件,记录变更。分区的数据在更新时,不要删除旧数据,保存新旧数据共存。元数据中存储具体的文件路径,而不仅仅是分区文件夹,可以看到下图的json文件和上图json文件所记录的元数据的区别。。
每一次的写入操作,会创建一个新的json文件,用递增的版本号命名,记录本次操作的文件。每当产生N个json,做一次聚合,记录完整的分区文件信息。用checkpoiot记录上次做聚合的版本号。
数据湖中的Transaction ACID
- Atomicity:本次写入要么对用户可见,要么不可见。
- Consistency:输入是什么,落盘的就是什么。
- Isolation:正确解决读写冲突和写写冲突。
- Durability:数据落盘后,即便服务器重启结果也不变。
保证原子性:新的写入写完parquet后开始写json文件,使用hash值对json文件命名,直到json文件内容写入完毕,利用HDFS将hash值命名的文件替换为版本号.json,到此为止commit完成,新的读取将会以该写入的版本号.json文件作为最新版。
事务隔离解决updata写入:从最新的版本中获取需要updata的分区,乐观锁先把要写入的文件全部落盘,然后写json文件。如果发现版本号和一开始没有区别,则直接写新的版本。如果发现版本号增加了,看看新增的这些版本有没有更新我要更新的分区,如果没有,写入新的版本,如果有,两者都更新了同一分区,得重新updata。
Schema Evolution
ID将data和metadata的列名一一对应
- 唯一确定的ID,新增列赋予新ID,删列ID不复用。
- 写入数据时,ID也写入数据文件。
- 读取数据时用ID做映射,可分为一下几种情况
- data中没有,matadata中有,则应为ADD操作。
- data中有,metadata中没有,则应为DROP操作
- data和metadata中都有同一ID但是其name不同,应为RENAME操作
- 如果同一列名而ID不同:应该是删除了一列,又增加了一列其列名与之前删除的列名一样。
Delta Lake、Hudi 与 Iceberg各自工作重点
Iceberg
- Schema evolution
- Partition evolution
- Hidden partition
- Time Travel
- Version Rollback
- ACID Transaction
Hidden partition: 传统的分区方式:数据中包含了date列,按照date分区,如果希望按照hour分区,则需要新增hour列。
Iceberg:分区方式:数据中心包含timestamp列,设置好partition transform方式,设置为date时,Iceberg帮助你转为date分区,这职位hour时,Iceberg帮你转为hour分区。按照需要进行转化。
Hudi
- Time service:Hudi管理transaction的方式
- Hudi Table Type:Copy on write/Merge on Read
- 高效的upserts(update/insert)
- 索引表:快速定位一条数据的位置
- Streaming Ingestion Service
Copy on write/Merge on Read:
Copy on write:在写的时候复制一份出来。将复制出的一份操作完后存储,如果数据有十万列但是只对其中几列进行操作,这样的话太浪费资源。如下图所示
Merge on Read:记录每次所操作的几列的信息,单独存储,在读取的时候把存储的几列信息与所有的数据进行合并操作。这样可以避免Copy on write的资源浪费情况,如下图所示。
Delta Lake
- ACID Transaction
- Schema校验
- 流批一体
- Time Trevel
- Upsert/Delete
- Z-Order优化