这是我参与 「第四届青训营 」 笔记创作活动的第10天
1. 发展历史
HDFS:难管理
数据湖最开始的概念——分布式存储HDFS
使用目录来区分不同的数据集
-
好处:
- 同一公司/组织可以使用共享存储
- 数据访问方便,灵活性高
-
坏处:
- 没有记录文件的schema(包括列名、列类型),经常使用schema on Query的方式
- 难以得知数据集包含了哪些文件,是通过什么样的分区组织
- 如果对个程序都在修改这个数据(修改数据、修改表结构),其他程序难以配合做修改
Hive:
对数据湖的演进——Hive Metastore
-
对数据湖中的数据集进行集中”定义”
- 他们都存在什么目录
- 数据集的schema是什么样子的
- 数据集有哪些分区,每个分区的目录是什么
数据仓库:
数据仓库是将数据从数据源提取和转换,加载到目的地
湖仓一体
| 数据仓库 | 数据湖(阶段一) | |
|---|---|---|
| 成本 | 高 | 低 |
| 存储计算分离 | 否 | 是 |
| ACID | 是 | 否 |
关于数据湖:
- 数据相关概念比较新,一直处在演进当中
- 一开始是 HDFS ,裸pb、txt 日志等,叫数据湖(管不了了就是数据沼泽)
- Iceberg、Hudi、Delta Lake,数据湖概念基本等于这些产品
2. 核心技术
Time travel:
要点:
- 每次写入都生成一个新的元数据文件,记录变更
- 分区数据在 Update 时,不要删除旧数据,保证新旧共存
- 元数据中存储具体的文件路径,而不仅仅是分区文件夹
写入流程”
- 写入parquet数据文件
- 写入 json 元数据文件
读写冲突:
如何确保原子性?(从用户可见性入手)
- 用户只会读取以版本号数字命名的json文件,每次都读取到最大的版本号作为数据集的现状
- 新的写入写完parquet后开始写json文件,使用hash值对json文件命名a2fs4hfg8ee.json
- 直到json文件内容写入完毕,利用hdfs的renameIfAbsent能力将a2fs4hfg8ee.json ,到此为止 commit 完成,新的读取将会以 000006.json作为最新的版本
读写冲突已经解决:
- 新的写入除非已经commit,否则用户读不到
- 用户正在读的分区,被另一个写入进行了更新,数据不会进行替换,而是共存
写写冲突:
| 写写冲突 | insert | update/delete |
|---|---|---|
| insert | can not conflict | |
| update/delete | can conflict | can conflict |
update 写入流程:
-
从最新的版本中,获取需要 update 的分区
-
乐观锁先把该写入的文件全落盘,然后写入json阶段
-
分几种情况:
-
发现版本号和一开始没区别,直接写新的版本
-
发现版本号增加,看看新增的这些版本有没有更新我要更新的分区
- 没有,直接写新的版本
- 有,两者更新了同一分区,得重新update了
-
Schema Evolution
Id将 data 和 metadata 的列名做一一对应
-
唯一确定的 ID 。新增列赋予新ID。删除 ID 不复用
-
写入数据时,ID也写入数据文件
-
读取数据时,用 ID 做映射,如果
- data 中没有,metadata 中有:ADD
- Data 中有,metadata 中没有:DROP
- Data 和 metadata 中都有同一个 ID ,但是 name 不同:RENAME
- 如果都有同一列名,而 ID 不同?先增加,再删除
3. 各有所长
Iceberg 工作重点
用户体验:
- Schema evolution
- partition evolution
- hidden partition
- time travel
- version rollback
性能:
- 快速 file plan
- 更多的 filter 方式
可靠性:
ACID transaction
完全开源,由Apache 孵化开发
well-designed Metadate Layer
Metadata files 定义了表结构,存储了snapshot 信息,分区列信息等 Manifest lists 存储了一个 snapshot 中所有 manifest的信息 Manifests 存储了一些 data files 的信息 Data files 就是具体的数据文件
data file filter
一些有助于 filter 的数据被层层记录,比如:
- Manifest file 记录了每个 data file 的分区范围
- Manifest list 记录了每个 manifest file 的分区范围分区可以被快速定位!可以做manifest list 级别裁剪.
- Manifest file 记录了每个 data file 每一列的最大值,最小值可以通过其他的列 (Userld) 做data file 级别裁剪。
Hidden Partition(隐藏分区)
传统的分区方式 数据中包含了date列,则按照date分区;如果希望按照hour分区,则需要新增hour列
lceberg的分区方式: 数据中包含 timestamp 列,设置好 partition transform 方式
- 设置为 date 时,iceberg 帮你转化为 date 分区 设置为 hour时,iceberg 帮你转化为 hour 分区 lceberg 记录了这层转化关系,并且按你的需要进行 partition evolution
Hudi
Hadoop Upsert Delete and Incremental Hudi工作重点:
- Timeline service: Hudi 管理 transaction 的方式
- Hudi Table Type: Copy on Write / Merge on Read
- 高效的 Upserts: update or insert
- 素引表:快速定位一条数据的位置
- Streaming Ingestion Service
- 完全开源,由 Apache 孵化
Timeline Srrivce & Upsert & Incremental
- Timeline Service: 记录的信息类似于metadata
- Upsert: 每一条样本都有一个主健PK, 当Upsert一条数据时,如果现有的数据中有这个PK,则 update 这条数据。否则白接 insert 这条数据
- Incremental: 某个时间点后新增的数据
Copy on write
Merge On Read
Delta Lake 工作重点
- ACID Transaction
- Schema 校验(不是evolution)
- 流批一体
- Time Travel
- Upsert/Delete
- Z-Order 174
- 只开源了一部分,由 Databricks 自己主导开发,Z-order 等优化的实现末开源