Delta Lake 是一个开源存储框架,用于在 Lakehouse 架构中的对象存储之上构建数据湖。 Delta Lake支持 ACID 事务、可扩展的元数据处理以及统一的流和批数据处理。 Delta Lake 通常用于为 Apache Spark 应用程序提供可靠性、一致性和可扩展性。 Delta Lake 运行在现有数据湖存储(例如 MinIO)之上,并且与 Apache Spark API 兼容。
最初的 Delta Lake 论文( Delta Lake:云对象存储上的高性能 ACID 表存储)描述了它是如何为云对象存储构建的。当Vertica 测试使用 Delta Lake作为外部表时,他们依赖于 MinIO。 HPE Ezmeral Runtime Enterprise 客户在 MinIO 上运行 Delta Lake 。 MinIO 支持 Delta Lake 对持久性的要求,因为 MinIO 对分布式和独立模式下的所有 I/O 操作都遵循严格的写入后读取和写入后列表一致性模型,并且被广泛认为可以运行 Delta Lake 工作负载。
许多组织依靠 MinIO 和 AWS S3 等云原生对象存储来存储大型结构化、半结构化和非结构化数据集。每个表都存储为一组 Parquet 或 ORC 对象,并排列成分区。对大文件的查询基本上是快速执行的扫描。
如果没有 Delta Lake,更复杂的 Spark 工作负载,特别是那些修改、添加或删除数据的工作负载,将在多用户/多应用负载繁重的情况下面临性能和正确性的挑战。多对象更新不是原子的,查询也不是孤立的,这意味着如果在一个查询中进行删除,那么当原始查询更新每个对象时,其他并发查询将获得部分结果。回滚写入很棘手,更新过程中的崩溃可能会导致表损坏。真正的性能杀手是元数据——对于包含数百万个对象(即保存数十亿或数万亿记录的 Parquet 文件)的海量表,元数据操作可能会使构建在数据湖上的应用程序完全停止。
Delta Lake 旨在将数据库的事务可靠性与数据湖的水平可扩展性结合起来。 Delta Lake 旨在通过 MinIO 等云原生对象存储上的 ACID 表存储层来支持 OLAP 式工作负载。正如《Delta Lake:基于云对象存储的高性能 ACID 表存储》一文中所述,“Delta Lake 的核心思想很简单:我们使用写入方式以 ACID 方式维护有关哪些对象是 Delta 表一部分的信息。提前日志本身存储在云对象存储中。”对象以 Parquet 进行编码,并且可以由理解 Parquet 的引擎读取。多个对象可以“以串行方式同时更新,同时仍然实现高并行读写性能”。该日志包含元数据,例如每个文件的最小/最大统计信息,“使元数据搜索速度比直接在对象存储中搜索文件快几个数量级”。
Delta Lake 提供以下功能:
Lakehouse 架构,特别是 Delta Lake,为基于对象存储构建的数据湖带来了关键的新功能。 Delta Lake 可与大量且不断增长的应用程序和计算引擎配合使用,例如 Spark、Starburst、Trino、Flink 和 Hive,还包括适用于 Scala、Java、Rust、Ruby 和 Python 的 API。 Kubernetes 原生 MinIO 专为云而构建,可在任何地方(边缘、数据中心和公共/私有云)实现高性能、弹性和安全的数据湖应用程序。
Delta 表是一起存储在目录(对于文件系统)或存储桶(对于 MinIO 和其他对象存储)中的文件集合。对于对象存储的读写,Delta Lake 采用路径的方案来动态识别存储系统,并使用相应的 LogStore 实现来提供 ACID 保证。对于 MinIO,您将使用 S3A,请参阅存储配置 — Delta Lake 文档。至关重要的是,Delta Lake 使用的底层存储系统能够像 MinIO 一样进行并发原子读/写。
创建增量表实际上是将文件写入目录或存储桶。增量表是通过写入(读取)Spark DataFrame 并指定delta
格式和路径来创建(打开)的。以 Scala 为例:
// Create a Delta table on MinIO: spark.range(5).write.format("delta").save("s3a://<your-minio-bucket>/<path-to-delta-table>") // Read a Delta table on S3: spark.read.format("delta").load("s3a://<your-mnio-bucket>/<path-to-delta-table>").show()
Delta Lake 依赖于每个表一个存储桶,并且存储桶通常根据文件系统路径建模。 Delta Lake 表是一个包含数据、元数据和事务日志的存储桶。该表以 Parquet 格式存储。表可以分为多个文件。 MinIO 支持 S3 LIST,以使用文件系统样式路径有效列出对象。 MinIO 还支持字节范围请求,以便更有效地读取大型 Parquet 文件的子集。
由于业界领先的性能,MinIO 成为 Delta Lake 表的绝佳选择。 MinIO 将可扩展性和高性能相结合,使每个工作负载(无论要求有多高)都触手可及。 MinIO 具有惊人的性能 -最近的基准测试在 GET 上实现了 325 GiB/s (349 GB/s),在 PUT 上实现了 165 GiB/s (177 GB/s),仅使用 32 个现成 NVMe SSD 节点。 MinIO 不仅仅提供为 Delta Lake 上最苛刻的工作负载提供支持所需的性能。
Delta Lake 存储桶可能会包含许多 Parquet 和 JSON 文件,这与我们在 MinIO 中内置的用作数据湖的所有小文件优化非常吻合。小对象与元数据内联保存,减少了读取和写入 Delta Lake 事务等小文件所需的 IOPS。
大多数企业需要 Delta Lake 的多云功能。 MinIO 包括主动-主动复制,可在本地、公共/私有云和边缘等位置之间同步数据。主动-主动复制使企业能够构建多地理位置弹性和快速热热故障转移。每个存储桶或 Delta Lake 表都可以单独配置为复制,以获得最大的安全性和可用性。
将ACID(原子性、一致性、隔离性和持久性)事务添加到数据湖中是一件相当大的事情,因为现在组织对数据湖中存储的大量数据拥有更大的控制权,因此也具有更大的信任度。以前,依赖 Spark 与数据湖合作的企业缺乏原子 API 和 ACID 事务,但现在 Delta Lake 使这成为可能。数据在捕获和写入后可以更新,并且在ACID的支持下,如果应用程序在操作过程中出现故障,数据也不会丢失。 Delta Lake 通过充当 Spark 和 MinIO 之间的中介来读取和写入数据来实现这一目标。
Delta Lake 的核心是DeltaLog ,它是用户和应用程序进行的交易的有序记录。用户在 Delta Lake 表上执行的每个操作(例如 UPDATE 或 INSERT)都是由多个操作或作业组成的原子提交。当每个操作成功完成时,提交将被记录为 DeltaLog 中的一个条目。如果任何作业失败,则提交不会记录在 DeltaLog 中。如果没有原子性,如果出现硬件或软件故障,导致数据仅被部分写入,数据可能会被损坏。
Delta Lake 将操作分解为以下一项或多项操作:
添加文件 - 添加文件
删除文件 - 删除文件
更新元数据 - 记录表名称、架构或分区的更改
设置事务 - 记录流作业已提交数据
提交信息 - 有关提交的信息,包括操作、用户和时间
更改协议 - 将 DeltaLog 更新为最新的软件协议
它并不像看起来那么复杂。例如,如果用户向表中添加新列并向其中添加数据,则 Delta Lake 将其分解为其组件操作 - 更新元数据以添加列并为每个添加的新文件添加文件 - 并将它们添加到完成后进行 DeltaLog。
Delta Lake 依靠乐观并发控制来允许给定表的多个读取器和写入器同时在该表上工作。乐观并发控制假设不同用户对表所做的更改可以在不发生冲突的情况下完成。随着数据量的增长,用户处理不同表的可能性也会增加。如果同时发生两个或多个提交,Delta Lake 会序列化提交并遵循互斥规则。通过这样做,Delta Lake 实现了 ACID 所需的隔离,并且在多次并发写入后,表看起来与这些写入连续且彼此独立地发生时的情况相同。
当用户对自上次读取以来已修改的打开表运行新查询时,Spark 会查阅 DeltaLog 以确定新事务是否已发布到该表,并使用这些新更改更新用户的表。这可以确保用户的表版本与 Delta Lake 中的主表同步到最新操作,并且用户不能对表进行冲突的更新。
DeltaLog、乐观并发控制和模式实施(与发展模式的能力相结合)确保了原子性和一致性。
当用户创建 Delta Lake 表时,会在_delta_log
子目录中自动创建该表的事务日志。当用户修改表时,每次提交都会以 JSON 文件的形式按升序写入_delta_log
子目录,即000000.json
、 000001.json
、 000002.json
等。
假设我们从数据文件1.parquet
和2.parquet
向表中添加新记录。该交易被添加到 DeltaLog 并保存为文件000000.json
。稍后,我们删除这些文件并添加一个新文件3.parquet
。这些操作被记录为新文件000001.json
。
添加1.parquet
和2.parquet
后,将其移除。事务日志包含这两个操作,即使它们相互抵消。 Delta Lake 保留所有原子提交,以启用完整的审计历史记录和时间旅行功能,向用户显示表在特定时间点的外观。此外,在运行VACUUM作业之前,文件不会快速从存储中删除。 MinIO版本控制提供了另一层防止意外删除的保证。
Delta Lake 通过在持久介质上存储表和事务日志来实现持久性。文件永远不会被覆盖,必须主动删除。写入存储的所有数据更改在发生时都可供用户自动使用。部分文件和损坏的文件已成为过去。 Delta Lake 不会在 RAM 中保存表和日志很长时间,而是直接将它们写入 MinIO。只要提交数据记录在 DeltaLog 中并且 JSON 文件写入存储桶,即使系统或作业崩溃,数据也是持久的。
MinIO 通过多种机制保证表及其组件写入后的持久性:
MinIO 使用加密来保护 Delta Lake 表的安全,并结合使用 IAM 和基于策略的访问控制来管理对它们的访问。 MinIO 使用 AES-256-GCM、ChaCha20-Poly1305 和 AES-CBC 等现代行业标准加密算法,通过 TLS 加密传输中的数据,并通过粒度对象级加密对驱动器上的数据进行加密。 MinIO 与外部身份提供商集成,例如 ActiveDirectory/LDAP、Okta 和 Keycloak for IAM。然后,用户和组在尝试访问 Delta Lake 表时将受到与 AWS IAM 兼容的 PBAC 的约束。
本节介绍如何使用单集群模式在 MinIO 上快速开始读写 Delta 表。
/home/spark
。hadoop-aws-2.6.5.jar
- Delta Lake 需要hadoop-aws
包中的org.apache.hadoop.fs.s3a.S3AFileSystem
类,该类实现了适用于 S3 的 Hadoop FileSystem
API。确保此包的版本与构建 Spark 所用的 Hadoop 版本相匹配。aws-java-sdk-1.7.4.jar
使用 Delta Lake 启动 Spark shell(Scala 或 Python)并以交互方式运行代码片段。
在斯卡拉中:
bin/spark-shell --packages io.delta:delta-core_2.12:1.2.1 --conf "spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension" --conf "spark.sql.catalog.spark_catalog=org.apache.spark.sql.delta.catalog.DeltaCatalog"
运行以下命令启动 Spark shell,并支持 MinIO 的 Delta Lake 和 S3:
bin/spark-shell \ --packages io.delta:delta-core_2.12:1.2.1,org.apache.hadoop:hadoop-aws:3.3.1 \ --conf spark.hadoop.fs.s3a.access.key=<your-MinIO-access-key> \ --conf spark.hadoop.fs.s3a.secret.key=<your-MinIO-secret-key> --conf "spark.hadoop.fs.s3a.endpoint=<your-MinIO-IP:port> \ --conf "spark.databricks.delta.retentionDurationCheck.enabled=false" \ --conf "spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension" \ --conf "spark.sql.catalog.spark_catalog=org.apache.spark.sql.delta.catalog.DeltaCatalog"
使用 MinIO 客户端为 Delta Lake 创建存储桶:
mc alias set minio http://<your-MinIO-IP:port> <your-MinIO-access-key> <your-MinIO-secret-key> mc mb minio\delta-lake
尝试一下并使用 Scala 创建一个简单的 Delta Lake 表:
// Create a Delta table on MinIO: spark.range(500).write.format("delta").save("s3a://delta-lake/demo1")
您将看到一些输出,表明 Spark 已成功写入表。
打开浏览器,使用您的访问密钥和秘密密钥通过http://<your-MinIO-IP:9001>
登录 MinIO。您将在存储桶中看到 Delta Lake 表:
MinIO 和 Delta Lake 的结合使企业能够拥有一个多云数据湖,作为统一的单一事实来源。查询和更新 Delta Lake 表的能力为企业提供了对其业务和客户的丰富洞察。各个团队都可以访问 Delta Lake 表来进行自己的分析或机器学习计划,因为他们知道自己的工作是安全的并且数据是及时的。
要深入了解,请下载 MinIO并亲自查看或在任何公共云上启动市场实例。你有问题吗?通过Slack或通过 [email protected] 提问。
也发布在这里。