简介
Delta Lake是Spark计算框架和存储系统之间带有Schema信息数据的存储中间层。它给Spark带来了三个最主要的功能:
第一,Delta Lake使得Spark能支持数据更新和删除功能;
第二,Delta Lake使得Spark能支持事务;
第三,支持数据版本管理,运行用户查询历史数据快照。
核心特性
- ACID事务:为数据湖提供ACID事务,确保在多个数据管道并发读写数据时,数据能保持完整性。
- 数据版本管理和时间旅行:提供了数据快照,使开发人员能够访问和还原早期版本的数据以进行审核、回滚或重现实验
- 可伸缩的元数据管理:存储表或者文件的元数据信息,并且把元数据也作为数据处理,元数据与数据的对应关系存放在事务日志中;
- 流和批统一处理:Delta中的表既有批量的,也有流式和sink的;
- 数据操作审计:事务日志记录对数据所做的每个更改的详细信息,提供对更改的完整审计跟踪;
- Schema管理功能:提供自动验证写入数据的Schema与表的Schema是否兼容的能力,并提供显示增加列和自动更新Schema的能力;
- 数据表操作(类似于传统数据库的SQL):合并、更新和删除等,提供完全兼容Spark的Java/scala API;
- 统一格式:Delta中所有的数据和元数据都存储为Apache Parquet。
Delta的特性实现是基于事务日志,比如ACID事务管理、数据原子性、元数据处理和时间旅行等功能。所以接下来详细介绍事务日志。
事务日志
事务日志是理解delta lake的关键,因为它是贯穿其许多最重要功能的公共线程,包括ACID事务、可伸缩元数据处理、时间旅行等等。
事务日志是什么?
是自delta lake表创建以来在该表上执行的每个事务的有序记录。当用户创建delta lake数据表时,该表的事务日志将自动创建在delta lake子目录_delta_log中。
事务日志路径,跟用户创建的表的数据文件和元数据文件存放在同一路径。
当用户对该表进行更改时,这些更改将作为有序的原子操作记录在事务日志中。每次提交都以json文件的形式写出,从000000.json开始。对表的其他更改将按升序数字顺序生成后续的json文件,以便下一次提交以000001.json的形式写出,下面以000002.json的形式写出,依此类推。
每次更改提交都拆分成原子操作,然后将这些原子操作有序的进行提交和操作,并记录在事务日志中。如下是给表增加4行数据事务日志,Delta会将这个操作拆分成4个原子操作,每个操作表示增加一行数据。
事务日志的工作方式?
1、每当用户执行修改表的操作(例如插入、更新或删除)时,Delta Lake会将用户的操作分解成如下一系列的原子操作组成的离散步骤:
- 添加文件–添加数据文件。
- 移除文件–移除数据文件。
- 更新元数据–更新表的元数据(例如,更改表的名称、模式或分区)。
- 设置事务–记录结构化流作业已提交具有给定ID的微批处理。
- 更改协议–通过将事务日志切换到最新的软件协议来启用新特征,可扩展性保证,比如存储系统可以增加新的软件。
- 提交信息–包含有关提交的信息,哪些操作是在何时何地执行的。
然后,将这些操作将作为有序的、称为提交的原子单元记录在事务日志中;
2、文件级事务日志:每个操作生成一个事务日志文件,日志文件中记录了所有的有序原子操作;
3、使用检查点文件,快速重新计算数据表状态:
delta lake每提交10次就会自动生成检查点文件。这些检查点文件在一个时间点上保存了整个表的状态,采用Parque格式,对spark来说既快捷又容易读取。换句话说,它们为spark阅读器提供了一种“快捷方式”,可以完全复制表的状态,从而使spark避免重新处理可能是数千个小而低效的json文件。
为了提高速度,spark可以运行listfrom操作来查看事务日志中的所有文件,快速跳到最新的检查点文件,并且只处理自保存最新的检查点文件以来所做的json提交。
4、以乐观并发方式处理并发读写,过程如下:
- 记录起始表版本
- 记录读/写
- 尝试提交
- 如果提交失败,重新读并检查读到的内容是否有变化
- 重复之前的步骤直到提交成功。
事务日志用途是什么?
1、唯一的真理来源
- 是跟踪所有用户对表所做的所有更改的中央存储库;
- 根据事务日志,保证用户看到的表始终是最新版本的;
- 用户不能对表进行不同的、有冲突的更改;
- 记录每一次操作成功后表的状态,包括对应的元数据等信息。
2、保证delta lake的原子性
只记录完全执行成功的事务(比如插入或更新),并将该记录作为唯一的真实来源,当发生错误和失败时,根据事务日志确定最新版本的完整数据。
3、数据版本管理:事务日志中会记录每个状态的表的时间戳和版本
4、审计:记录每次操作的详细信息,提供了一个可验证的过程流
使用方法
详细请参考:https://docs.delta.io/latest/index.html
Delta提供完全兼容Spark的Java/scala API。使用方法如下:
1、Delta包引入(前提是提前安装Spark 2.4.0以后的新版本)
2、配置底层的存储系统,目前Delta支持直接本地存储、HDFS、Amazon S3和Azure存储服务。默认为本地存储。
3、使用,目前完整的功能支持Java和Scala,部分功能支持Python。
目前支持的操作包括:
表批量读写:
创建表
分区数据
查看表
查看表的历史版本(根据时间戳或者版本号)
表更新写入
向表中追加数据
重新表中数据
自动更新表的schema
手工替换表的schema和分区
显示数据表的视图
表流式读写:
做为stream源
做为sink源
表的其他操作:
删除
更新
合并插入
其他命令:
vacuum:清空不再需要的数据
history:查看操作的历史记录,包括操作、用户和时间戳等信息
分析不足
最重要的事务日志直接跟数据存放在一起;
没有权限和用户管理;
不支持多表事务和外键,只支持单表级事务;
只有表级视图,没有整个数据湖的全局视图;