这是我参与「第四届青训营 」笔记创作活动的第7天
HDFS-分布式存储系统:
HDFS通过将文件分块来存储大文件,HDFS 的组件有NameNode和 DataNode,分别负责提供元数据和数据服务。在读/写数据时,HDFS客户端需要先从NameNode上获取数据读取/写入的DataNode地址,然后和DataNode交互来完成数据读/写。
Parquet-高性能列式存储:
过滤下推到存储侧,更好地压缩性能。
01.发展历史
数据湖三阶段:Hadoop、Hive、湖仓一体
1.1数据湖发展阶段-Hadoop
数据湖最开始的概念——分布式存储HDFS
使用目录来区分不同的数据集
好处: 同一公司/组织可以使用共享存储
数据访问方便,灵活性高
坏处:
1.没有记录文件的schema(包括列名、列类型),经常使用Schema on Query的方式
2.难以得知数据集包含了那些文件,是通过什么样的分区组织的
3.如果多个程序都在修改这个数据集(修改数据、修改表结构),其他程序难以配合做修改
1.2数据湖发展阶段2-Hive
数据湖的演进——Hive Metastore
对数据湖中的数据集进行集中“定义”
数据湖中存在了哪些数据集
它们都存储在什么目录
数据集的schema是什么样子的
数据集有哪些分区,每个分区的目录是什么
如果表是静态的,没有新增写入,则所有读取方都能很便捷的使用 产生问题, 我们需要Transaction ACID! 我们需要支持更多样的schema变更! And more!
1.3数据湖发展阶段3-湖仓一体
题外话——数据仓库
什么是数据仓库?
数据仓库将数据从数据源提取和转换,加载到目的地
数据仓库存储+计算不分离
数据仓库严格控制写入数据的schema
湖仓一体(数据湖的现状):
结合了数据湖和数据仓库的优势
将数据仓库中对于数据的严格管理直接实现到了低成本的分布式存储之上
Key Features:
Transaction ACID
Structured da
Schema管理
存储计算分离
支持多种计算引擎和文件格式
1.4 业界三大数据湖
项目名:Hudi,Iceberg,Delta Lake
1.5关于“数据湖”
数据相关概念比较新,一直处在演进当中
一开始是 HDFS,裸pb、txt日志等等,叫数据湖(管不动了就叫数据沼泽)
后来出现了lceberg、Hudi、Delta Lake了,数据湖概念就基本等于这些产品了
也更贴近于Lakehouse的概念
02.核心技术
湖仓—体项目解决的关键问题:Transaction、Schema变更、冲突解决
2.1 文件结构
写入数据湖时
1.按照每条数据的date进行分区
2.额外使用metadata文件记录表信息,
2.2 Time travel
要点:
1.每次写入都生成一个新的元数据文件,记录变更
2.分区数据在Update时,不要删除旧数据,保证新旧共存
3.元数据中存储具体的文件路径,而不仅仅是分区文件夹
1.每一次写入操作,创建一个新的json文件,以递增版本号命名,记录本次新增/删除的文件。
2.每当产生N个json,做一次聚合,记录完整的分区文件信息
3.用checkpoint记录上次做聚合的版本号
2.3 Transaction 事务
ACID,是指数据库在写入或更新资料的过程中,为保证事务是正确可靠的,所必须具备的四个特性。
以A给B转账10元为例:
1. Atomicity: 原子性——要么A-10 B+10,要么都不变
2. Consistency:一致性——不可以A-10 B+5
3. lsolation:事务隔离——A和C同时给B转10,B最终结果应是+20
4. Durability:持久性——转账服务器重启,结果不变
数据湖中的ACID:
1. Atomicity: 原子性-本次写入要么对用户可见,要么不可见(需要设计)
2. Consistency:一致性–输入是什么,落盘的就是什么(由计算引擎保证)
3. Isolation:事务隔离–正确解决读写冲突和写写冲突(需要设计)
4. Durability.持久性–落完数据后,即便服务器重启结果不变(由存储引擎保证)
2.3.1 原子性
写入流程:
1.写入parquet 数据文件
2.写入json元数据文件
如何确保原子性?(从用户可见性入手!)
1.用户只会读取以版本号数字命名的json文件,每次都读取到最大的版本号作为数据集的现状
2.新的写入写完parquet后开始写json文件,使用hash值对json文件命名,如a2fs4hfg8ee.json
3.直到json文件内容写入完毕,利用hdfs的renamelfAbsent能力将a2fs4hfg8ee.json替换为000006.json,到此为止commit完成,新的读取将会以000006.json作为最新版本
读写冲突已经被解决,how?
1.新的写入除非已经commit,否则用户读不到
2.用户正在读的分区,被另一个写入进行了更新,数据不会进行替换,而是共存
2.3.2 事务隔离
Update写入流程:
1.从最新的版本中,获取需要update的分区
2.乐观锁先把该写入的文件全落盘,然后进入写json阶段
3.分几种情况:
1.发现版本号和—开始没区别,直接写新的版本。
2.发现版本号增加了,看看新增的这些版本有没有更新我要更新的分区?
1.没有,直接写新的版本。
2.有,两者都更新了同—分区,得重新update 了.
2.4 Schema Evolution
Add/Drop/Rename
重要:
√用户并不直接读取parquet文件本身,而是通过数据湖接口读取,如Dataset<Row> ds = simpleDataLake.read(mytable).option(date=2020-01-01)
√数据湖内部会读取应该读的parquet,并在schema上做进一步处理
ID将data和metadata的列名做——对应!
1.唯—确定的ID。新增列赋予新ID。删列ID不复用。
2.写入数据时,ID也写入数据文件
3.读取数据时,用ID做映射,如果
1.Data中没有,metadata中有: ADD
2.Data中有,metadata中没有:DROP
3.Data和metadata中都有同—ID,但是name不同:RENAME
4.如果都有同—列名,而lD不同?
03.各有所长
不同湖仓体项目的独到之处
3.1 lceberg工作重点
用户体验
1. Schema evolution
2. Partition evolution
3. Hidden partition
4. Time Travel
5. Version Rollback
性能
1.快速file plan
2.更多的filter方式
可靠性
1. ACID Transaction
>完全开源,由Apache孵化开发
3.2 Hudi
Hadoop Upsert Delete and Incremental
Hudi工作重点:
1. Timeline service: Hudi管理transaction的方式
2. Hudi Table Type: Copy on Write /Merge on Read
3.高效的Upserts: update or insert
4. 索引表:快速定位—条数据的位置
5. Streaming lngestion Service6.完全开源,由Apache孵化
3.3 Delta Lake工作重点
1. ACID Transaction
2. Schema校验(不是evolution)
3.流批─体
4. Time Travel
5. Upsert/Delete
6. Z-Order优化
7.只开源了一部分,由Databricks自己主导开发,Z-order等优化的实现未开源
04。总结场景
三个湖仓—体项目的对比,数据湖在字节跳动中的应用
字节跳动数据湖场景举例–Feature Store
Feature Store及其平台
·基于Apache lceberg做了大量定制与优化
·站内存储约220 PB训练样本
√最大单表30PB,15K个特征
√相比 instance pb样本能节省约30%~ 50%空间
·平台端到端体验完整、用户使用成本低
√控制面板、特征监控、数据维护(样本回溯、TTL、脏数据处理等)
·对特征回溯及特征调研场景做了专门强化
√支持Update语义操作和数据分支
批流—体:近实时的数据写入与数据就绪(Readiness)
1.例子:消息队列直接入湖、流式Upsert
2.应用:能同时训最新(流式)和历史(批式) 合球动青训营
更强的算力:要求更快的读数据
1.例子:分布式任务扫描、向量化读与读时合并、统—内存格式(Apache Arrow)
2.应用:数据读取不应成为训练瓶颈