数据湖 | 青训营笔记

78 阅读4分钟

这是我参与「第四届青训营 」笔记创作活动的第9天

数据湖发展历史

第一阶段---Hadoop

数据湖最开始的概念——分布式存储HDFS使用目录来区分不同的数据集

  • /douyin
  • /20220623/20220624/toutiao

好处:

  1. 同一公司/组织可以使用共享存储中
  2. 数据访问方便,灵活性高

坏处:

  1. 没有记录文件的schema(包括列名、列类型),经常使用Schema on Query的方式
  2. 难以得知数据集包含了那些文件,是通过什么样的分区组织的
  3. 如果多个程序都在修改这个数据集(修改数据、修改表结构),其他程序难以配合做修改

第二阶段---Hive

Snipaste_2022-08-11_10-21-38.jpg 数据湖的演进——Hive Metastore 对数据湖中的数据集进行集中“定义”

  • 数据湖中存在了哪些数据集
  • 它们都存储在什么目录
  • 数据集的schema是什么样子的
  • 数据集有哪些分区,每个分区的目录是什么

第三阶段---湖仓一体

数据仓库:

  • 数据仓库将数据从数据源提取和转换,加载到目的地
  • 数据仓库存储+计算不分离
  • 数据仓库严格控制写入数据的schema

数据仓库和数据湖对比:

Snipaste_2022-08-11_10-26-00.jpg

Snipaste_2022-08-11_10-26-19.jpg
湖仓一体(数据湖的现状):

  • 结合了数据湖和数据仓库的优势
  • 的将数据仓库中对于数据的严格管理直接实现到了低成本的分布式存储之上
  • Key Features:
    • Transaction ACID
    • Schema管理
    • 存诸计算分离
    • 支持多种计算引擎和文件格式

数据湖核心技术

1.文件结构

写入数据湖时

  • 按照每条数据的date进行分区
  • 额外使用metadata文件记录表信息,如下图所示

Snipaste_2022-08-11_10-30-25.jpg

2.Time travel

要点:

  • 每次写入都生成一个新的元数据文件,记录变更
  • 分区数据在Update时,不要删除l旧数据,保证新旧共存
  • 元数据中存储具体的文件路径,而不仅仅是分区文件夹

Snipaste_2022-08-11_10-33-29.jpg

  • 每一次写入操作,创建一个新的json文件,以递增版本号命名,记录本次新增/删除的文件。
  • 每当产生N个json,做一次聚合,记录完整的分区文件信息
  • 用checkpoint记录上次做聚合的版本号

3.Transcation

ACID,是指数据库在写入或更新资料的过程中,为保证事务是正确可靠的,所必须具备的四个特性。 以A给B转账10元为例:

  • Atomicity: 原子性——要么A-10 B+10,要么都不变
  • Consistency:一致性——不可以A-10 B+5
  • Isolation:事务隔离——A和C同时给B转10,B最终结果应是+20
  • Durability:持久性——转账服务器重启,结果不变

数据湖中的ACID:

  • Atomicity: 原子性–本次写入要么对用户可见,要么不可见(需要设计)
  • Consistency:一致性–输入是什么,落盘的就是什么(由计算引擎保证)
  • lsolation:事务隔离–正确解决读写冲突和写写冲突(需要设计)
  • Durability:持久性–落完数据后,即便服务器重启结果不变(由存储引擎保证)

原子性实现

Snipaste_2022-08-11_10-38-13.jpg

写入流程:

  1. 写入parquet文件
  2. 写入json元数据文件

如何确保原子性?--从用户可见性

  • 用户只会读取以版本号数字命名的json文件,每次都读取到最大的版本号作为数据集的现状
  • 新的写入写完parquet后开始写json文件,使用hash值对json文件命名,如a2fs4hfg8ee.json
  • 直到ljson文件内容写入完毕,利用hdfs的renamelfAbsent能力将a2fs4hfg8ee.json替换为000006.json,到此为止commit完成,新的读取将会以000006.json作为最新版本

读写冲突已经被解决,how?

  • 新的写入除非已经commit,否则用户读不到
  • 用户正在读的分区,被另一个写入进行了更新,数据不会进行替换,而是共存

事务隔离

Snipaste_2022-08-11_10-42-45.jpg Update 写入流程:

  1. 从最新的版本中,获取需要update的分区
  2. 乐观锁先把该写入的文件全落盘,然后进入写json阶段
  3. 分几种情况:
    1. 发现版本号和—开始没区别,直接写新的版本。
    2. 发现版本号增加了,看看新增的这些版本有没有更新我要更新的分区?
      1. 没有,直接写新的版本。
      2. 有,两者都更新了同一分区,得重新update 了。

4.Schema Evolution

  • ID将data和metadata的列名做一—对应!
  • 唯一确定的ID。新增列赋予新ID。删列ID不复用。
  • 写入数据时,ID也写入数据文件
  • 读取数据时,用ID做映射,如果
    • Data中没有,metadata中有:ADD
    • Data中有,metadata中没有:DROP
    • Data和metadata中都有同—ID,但是name不同:RENAME