如今围绕数据湖仓一体架构的讨论很多,它统一了两种主流数据存储技术(数据仓库和数据湖),有望用更少的资源做更多的事情。另一方面,由于客户对支持开放格式所承诺的灵活性和开放性的需求,所有主要的数据仓库供应商都接受了开放表元数据格式的使用。
三个项目 - Apache Hudi、Apache Iceberg 和 Delta Lake - 现在是该领域所有关注和供应商的中心。这些项目对于为数据打造一个开放、适应性强的基础至关重要,使企业能够选择适合其独特工作负载的适当计算引擎,从而避免专有存储格式的限制。但是在这些项目中可以互换使用术语 开放表格式
和 开放数据湖仓一体
的激增,因此需要澄清和更深入的理解。
采用这些表格格式为开放性奠定了基础。尽管如此,重要的是要认识到,开放数据架构需要的不仅仅是开放的表格式,它还需要跨格式、目录和开放计算服务的全面互操作性,以便基本的表管理服务(如聚簇、压缩和清理)在本质上也是开放的。今天的许多倡导都是为了表明,用开放的表格格式替换专有的数据存储格式可以使数据架构开放且可互操作。实际上,客户最终会根据给定供应商的支持选择特定的开放表格格式,同时被绑定到专有服务和工具来满足其他基本需求。这为在组织内实现真正的开放数据架构带来了障碍。
我们希望通过此博客回答的问题是:
• 开放表格格式和开放数据湖仓一体平台有什么区别?
• 开放的表格格式是否足以实现真正的开放数据架构?
• 今天我们能如何无缝地跨不同平台移动?
为了帮助回答这些问题,我们将探索数据架构多年来的演变,将湖仓一体架构分解为各个组成部分,并执行一些比较分析,以区分哪些是开放的,哪些不是。让我们从一点历史开始。
数据架构的演变
多年来,组织在开发集中、可靠且可扩展的数据架构方面投入了大量资金。目标是为用户提供更多数据访问权限,允许更多使用者使用数据并促进分析工作负载,范围从商业智能 (BI) 到机器学习 (ML)。随着对这些工作负载的需求增加,数据架构不断发展,以适应现代数据处理和存储的复杂多样需求。在以下部分中,我们将分解数据架构从 OLTP(在线事务处理)到现代数据湖仓一体的演变,重点介绍每种系统中的关键技术组件及其结构。
OLTP
OLTP 系统一直是处理事务数据的基础。这些系统旨在一次高效处理一行或几行数据,支持插入、更新和删除等操作,使其成为高容量事务环境的理想选择。
传统上,数据库中没有与术语 "表格式" 等效的术语。它们仅指一种存储格式,这是从用户那里抽象出来的较低层技术细节。但是,本着本博客的重点,我们将 OLTP 中使用的存储格式分为文件和表格式。OLTP 数据库可以提炼成六个技术组件,包括存储、文件格式、表格式、存储引擎、计算引擎和系统目录。这些组件捆绑到一个系统中,用于事务处理。
OLTP 系统针对点查找和实时事务数据进行了优化(例如,存储格式使用行优化文件和索引)。它们不适用于需要扫描大量聚合数据的复杂分析查询。
OLAP/数据仓库
在线分析处理 (OLAP) 系统是首批专为高效查询聚合数据而设计的数据系统之一。这些系统通常称为数据仓库,充当中央存储库,存储来自不同来源的数据,并针对查询大量信息进行了优化。传统上,这些系统构建在行存储 RDBMS 之上,具有为分析查询模式、计算引擎和存储机制量身定制的专用优化器。但是列式存储(其中数据按列而不是行组织和存储)的引入使 OLAP 数据库能够利用高效压缩并更快地访问分析查询中的特定属性。
OLAP 数据库擅长管理结构化数据,对于进行复杂的查询和分析至关重要,这是商业智能 (BI) 工作负载的基础。与 OLTP 类似,基于 OLAP 的系统将 6 个技术组件捆绑到一个单元中;请注意文件格式现在是面向列的,而不是面向行的,并且计算引擎针对不同的目的进行了优化。
OLAP 非常适合针对结构化数据进行分析,但其处理半结构化和非结构化数据的能力是有限的,这对于机器学习 (ML) 等更高级的应用程序至关重要。OLAP 的这一限制凸显了更通用的数据架构的必要性。
数据湖
数据湖始于 Hadoop 时代,作为解决数据仓库局限性的解决方案,特别是它们在处理各种类型数据(结构化、半结构化和非结构化)方面的效率低下和高运营成本。从更技术意义上讲,数据湖利用分布式文件系统或对象存储以开放文件格式(如 Apache Parquet 和 Apache ORC)提供可扩展、低成本的存储。数据湖架构还避免了数据读/写路径中长时间运行的组件,因此计算也可以弹性扩展 - 与从数据仓库读取/写入相比,通常为 10-100 倍,数据仓库通常具有很少的节点集群。
与数据仓库不同,数据湖支持读时架构,允许以显著降低的成本存储数据。数据湖引入了计算和存储组件的分离,使组织能够独立扩展这些资源,从而提高灵活性并优化成本。
对于数据湖架构,组织通常采用两层方法:在云数据湖中利用开放文件格式(如 Parquet)进行机器学习和高级分析工作负载,同时有选择地导出数据以添加到现有数据仓库中,以实现商业智能 (BI) 和临时查询支持。这种两层方法会增加复杂性和开销,通常会导致数据过时和额外的数据副本。
图 5.具有数据湖和数据仓库的两层架构。基于 ML 的工作负载在各种数据类型上运行,在数据湖中(左),而 BI 和 Ad Hoc 查询在数据仓库中的单独数据上运行(右)。
数据湖仓一体
虽然数据湖提供了可扩展且经济高效的存储解决方案,但它们缺乏 DBMS 的许多功能。特别是缺少存储引擎和表格式,它们无法支持 ACID 事务保证。这会导致在写入和读取数据时出现可靠性问题,尤其是在并发写入时。为了解决这一关键缺点,数据湖仓一体架构引入了事务数据库层,同时保留了数据湖架构的优势,即无限存储和弹性计算。
湖仓一体中的事务功能是通过将存储引擎组件与存储格式(现在通常称为表格式)相结合来实现的,该格式充当 Parquet 等文件格式之上的开放元数据层。事务数据库层在现有数据湖存储之上集成了关键的 DBMS 功能,例如 ACID 事务、索引、并发控制和表维护服务(例如聚簇、压缩、清理)。
最重要的是,Lakehouse 架构将传统数据仓库的紧密耦合组件解构为更加模块化的框架。数据以开放文件和表格式存储在湖仓一体中,允许不同的计算引擎协同处理相同的数据,而事务数据库层提供传统 DBMS 的强大特性,确保不同工作负载的数据完整性和事务一致性。
通用 Lakehouse 架构
在我们深入讨论这些组件之前,出于本博客的目的,有必要区分数据湖仓一体架构和数据湖仓一体平台。我们建议对这些术语进行以下定义。
Lakehouse 架构
Lakehouse 架构提供了一个参考蓝图或设计模式,该模式显示了系统的不同层和组件如何交互,以将数据仓库和数据湖的功能集成到一个统一的系统中。Lakehouse 架构由多个层组成,包括摄取、存储、元数据、事务数据库和消费服务,每个层在管理和处理数据方面都扮演着特定的角色。将其视为建筑物的蓝图,概述了不同的房间、公用设施和结构元素将如何布置和交互;如何建造建筑物的计划。
Lakehouse 平台
Lakehouse 平台是指 Lakehouse 架构的实际实现。Lakehouse 平台是一个功能系统,它通过集成管理、处理和分析数据所需的各种工具、技术组件和服务来实现架构的蓝图。建筑是蓝图,而平台是实际的建筑,使用特定的材料和技术建造。
Lakehouse 架构中的组件
让我们更深入地了解湖仓一体架构的每一层/组件。
• 湖存储: 此层包括云对象存储(保存对象 - 文件的存储,以及每个文件的任何元数据),其中存储来自各种操作系统的文件,这些文件在通过 ETL/ELT 流程摄取后进行存储。这是一种获取字节,将它们组合成一个文件,并将文件保存到文件系统中的指定路径的方法。Lake Storage 层支持存储任何数据类型,并且可以根据需要进行扩展。
• 文件格式: 文件格式保存实际的原始数据,这些数据以物理方式存储在存储层(对象存储)中。这些格式决定了数据在每个文件中的组织方式 - 无论是结构化、半结构化还是松散结构/非结构化形式。它们还确定数据的排列方式,即以基于行的方式或列式方式。
• 存储/表格格式: 表格式或存储格式充当文件格式层上的开放元数据层。它提供了一个抽象,将文件的逻辑表示与物理数据结构分开。表格式在不可变数据文件上定义架构,启用事务功能,并为读取器和写入器提供 API 以与数据交互。
• 存储引擎: 存储引擎层负责管理 Lakehouse 架构中的底层数据,确保所有文件和数据结构(如索引)都得到良好的维护、优化和最新。存储引擎通过支持核心特性来确保事务完整性:原子性、一致性、隔离性和持久性 (ACID),这对于确保数据准确性和可靠性至关重要,尤其是对于并发事务。它还处理关键的表管理服务,例如聚簇、压缩、清理和索引,并与表格式相结合,以优化数据布局,从而提高查询性能和操作效率。
• 目录: 目录层对于在 Lakehouse 架构中实现高效的搜索和数据发现至关重要。它跟踪所有表及其元数据,对表名称、架构和对与每个表的格式关联的特定元数据的引用进行编目。
• 计算引擎: 计算引擎层由负责处理数据的引擎组成,确保读取和写入操作都能高效执行。它使用表格式提供的基元和 API 与底层数据交互,管理实际的处理任务。
现在我们已经定义了每个组件并了解了它们的功能,我们可以看到开放式湖仓一体架构与传统数据仓库的架构非常相似。然而,关键区别在于,数据湖仓一体中的每个组件都是开放和模块化的,可以灵活地混合和匹配这些组件,以满足特定的用例要求。这里需要注意的另一件重要事情是,湖仓一体中的事务数据库层与存储引擎和表格式一起提供,这是它与数据湖架构的区别。事实上,存储引擎层提供的服务对于使湖仓一体正常运行并优化它们以提高查询性能至关重要。
随着我们深入研究开放式湖仓一体的架构,必须解开其最关键的组成部分之一:表格式。这个术语以及其他术语,如元数据格式、存储格式和开放湖仓一体格式,往往会导致混淆,因为这些概念通常不会孤立地讨论。了解表格格式的细微差别将有助于我们解决前面提出的重要问题,这些问题涉及它们与开放式湖仓一体平台有何不同,以及它们是否是实现真正开放数据架构所需的全部内容。在下一节中,我们将阐明表格式的真正含义及其在实现开放数据架构中的作用。
了解表格式
与某些人的想法相反,表格式并不是一个新概念。它们类似于数据库多年来所说的存储格式。它们的根源可以追溯到关系数据库的早期,在 Oracle 等系统中实施了 Edgar Codd 的关系模型。从历史上看,Oracle 和 Microsoft 等 OLTP 数据库供应商允许用户以结构化表的形式查看数据集(文件),由数据库的存储引擎管理,本机计算引擎与这些底层文件进行交互。这些表格格式本质上是专有的,因此是封闭的,即只能由本机计算引擎访问。
然后,在大数据世界中,随着基于 Hadoop 的数据湖的出现,MapReduce 框架最初是访问和处理存储在 Hadoop 文件系统 (HDFS) 中的数据文件的唯一方式。但是,访问存储在 HDFS 中的数据需要编写特定于 MapReduce 的 Java 代码,这意味着它仅限于专业工程师。
因此,创建了 Apache Hive 等计算引擎,以便更多人(例如数据分析师)可以访问存储在数据湖中的数据。这需要定义数据集的架构以及如何将该数据集引用为表,从而使引擎能够与架构进行交互。这导致了 Apache Hive 表格式的发展。它允许使用 Hive 查询语言 (HiveQL) (一种类似于 SQL 的查询语言)对数据进行民主化。Hive 表格式标志着新一代独立表格式的开始。
有了这个历史背景,让我们更深入地了解什么是表格格式。在上一节中,我们将其定义为文件格式层上的开放元数据层 - 将文件的逻辑表示与物理数据结构分开的抽象。详细地说,表格式组织数据集的文件以将它们呈现为单个表。此抽象允许多个用户和工具同时与数据交互,无论是出于写入还是读取目的。表格式包括一组读取器和写入器 API,并跟踪元数据信息。
这是表格式元数据的典型组成:
• 架构信息: 描述表的结构,包括列名称、数据类型和任何嵌套结构(如数组或结构)。
• 分区信息: 列出每个分区的特定值或值范围,以便在查询执行期间快速识别相关分区。
• 统计信息: 包括基于 Parquet 数据文件的每列的行数、null 数和最小值/最大值等信息。这通过提供可用于有效筛选数据的详细信息来帮助查询优化。
• 提交历史记录: 跟踪对表所做的所有更改,包括插入、更新、删除和架构更改。这允许时间旅行查询和版本回滚。
• 数据文件路径: 列出属于表的数据文件的路径,通常包含有关它们所属分区的详细信息。
在对表格格式有了全面的了解之后,让我们将重点转移到 Lakehouse 表格格式。Hudi、Iceberg 和 Delta Lake 是湖仓一体架构中广泛使用的三种开放表格式。这些元数据格式带来了以下功能:
• 支持基于 ACID 的事务: 表格式与存储引擎相结合,支持 ACID 事务,允许可靠地执行操作(例如插入、更新插入和删除),并确保并发操作不会导致冲突或损坏。
• Schema演进: 这些格式支持 Schema演进,允许用户随着时间的推移更改表的 Schema,而不会中断现有查询。可以在保持与以前版本数据的兼容性的同时进行添加、重命名或删除列等更改。
• 时间旅行和数据版本控制: 湖仓一体表格格式允许用户使用时间旅行查询数据的历史版本。这意味着可以访问数据在特定时间点的状态,这对于启用一系列不同类型的查询以及审计和调试至关重要。
这些功能对于在 Lakehouse 架构中运行分析工作负载至关重要。然而,现代表格式的关键要点是它们的开放性。这种开放性确保与特定表格式兼容的任何引擎都可以访问数据,从而将它们与供应商特定数据库和数据仓库中使用的专有(封闭)表格式区分开来。
现在,我们已经探讨了表格式的细微差别并区分了 Lakehouse 架构和平台,现在是解决我们打算回答的最初问题的好时机:**开放式表格式和开放式 Lakehouse 平台之间有什么区别?**在开放湖仓一体架构的更广泛上下文中,开放表格式只表示一个独立的组件(图 7),该架构还包括其他元素,例如文件格式、存储引擎、计算引擎和目录。该组件主要用作位于实际数据文件之上的元数据层,有助于实现独立且开放的数据层,可供各种计算引擎访问。
另一方面,开放式 Lakehouse 平台将每个组件(存储、文件格式、表格式、存储引擎、计算和目录)集成到一个有凝聚力的系统中。由于这些组件是开放和模块化的,因此该平台提供了根据特定用例在各种选项之间切换的灵活性。
开放数据架构的要求
我们之所以必须更深入地研究开放表格式和开放湖仓一体平台之间的区别,是因为有一种普遍的观念认为,采用开放表格式会自动确保数据架构内的开放性和互操作性。虽然这些表格格式为开放生态系统奠定了基础,但简单地声称这就是实现真正开放数据架构所需的全部内容是不正确的。还有几个重要因素还必须考虑。以下是一些实际的考虑因素。
• 组件的开放标准: 对于真正的开放数据架构,技术组件本身必须是开放且可互操作的。采用开放标准并不一定意味着使用自我管理的开源解决方案。由于工程成本和维护要求高昂,许多组织会选择供应商管理的解决方案来满足其计算和存储需求。但是在选择供应商平台时,确保没有平台锁定并且数据仍然可以从多个计算引擎访问,这一点至关重要。这种灵活性允许混合和匹配“最佳”解决方案,并有可能在未来需要时更换供应商。
• 表格格式之间的互操作性: 开放表格格式为构建开放数据架构提供了灵活性,但由于每种格式具有独特的优势,选择正确的格式仍然是一个具有挑战性的决定。例如,Hudi 在更新繁重的环境中表现出色,并与 Spark、Flink、Presto 和 Trino 很好地集成。Apache Iceberg 针对读取操作进行了优化,而 Delta Lake 主要在具有 Spark 的 Databricks 生态系统中使用。此外随着 Lakehouse 系统的发展以支持使用多种表格式的较新工作负载,组织需要通用的数据可访问性。这意味着数据必须在任何计算平台上一次写入、在任何位置查询。这就是 Apache XTable(孵化)等开源项目通过轻量级元数据转换提供各种表格格式之间的互操作性的地方。
• 目录之间的互操作性: 虽然开放表格式拓宽了对数据的访问,但数据目录是湖仓一体架构中的另一个组件,通常由供应商控制。如今的供应商平台需要使用专有目录来利用对这些开放表格格式的全面支持,从而创造一种新的锁定形式。这种依赖关系限制了与特定平台不支持的其他查询引擎的互操作性,迫使组织将其数据管理局限于单个供应商的生态系统。在某些情况下,组织内的不同团队使用遵循相同规范(例如 Iceberg REST)和标准(例如使用相同的 API)的不同目录。但是尽管在某些级别上具有一致性,但没有一种简单的方法可以在这些目录之间同步数据,而无需根据元数据重新创建或迁移表。请注意,Apache Iceberg 中的 register_table 等方法会警告不要在多个目录中注册,因为这样做可能会导致缺少更新、表损坏和数据丢失。此外,虽然此过程对于较小的数据集可能是可管理的,但在大规模情况下是不切实际的。由于每个目录都有自己的访问控制策略,这些策略不适用于其他目录,因此它还会阻止通用数据访问。此类场景强调了对开放、可互操作的目录的需求,这些目录可以桥接不同的平台。
• 开放平台和表服务: 在湖仓一体架构中,数据缩减、聚簇、索引和清理等表管理服务对于优化数据布局以实现高效的查询处理至关重要。作为对这些功能的补充,平台服务为数据工作流提供了特定功能,并与数据写入器和读取器交互,包括用于摄取、导入/导出打开的表和目录同步的工具。传统上,客户依赖封闭的专有平台来实现这些功能,这限制了灵活性。为了真正利用开放数据架构,迫切需要这些服务是开放的和可互操作的,允许用户管理数据源并保持最佳表性能,而无需受制于供应商特定的解决方案。这种开放性确保数据架构可以保持灵活性,适应新出现的需求,而不会受到供应商限制。
现在回到我们的问题 - 开放的表格格式是否足以实现真正的开放数据架构?
总而言之,仅仅将封闭数据架构/平台中的专有表格格式替换为 Hudi、Iceberg 或 Delta Lake 等开放表格格式并不能构成完全开放的数据架构。开放式数据架构需要确保所有组件(包括开放式表格式、目录和表管理服务(存储引擎的一部分))都是开放的,最重要的是要实现互操作性。完全开放的方法使组织能够在出现新需求时,在特定组件或整个平台(无论是供应商管理的还是自我管理的开源解决方案)之间无缝切换。这种灵活性可以防止新形式的锁定,并支持通用数据可访问性。
开放数据湖仓一体平台参考实现
这将我们带到了本博客的最后一部分。鉴于我们已经花费了大量时间来理解 Lakehouse 架构的术语和术语,因此将所有这些内容放在一起,看看一个开放且可互操作的 Lakehouse 平台是什么样的是有意义的。我们将以 Hudi 的 Lakehouse 平台为例。但是,此讨论不仅限于开源解决方案。供应商管理的 Lakehouse 平台或其他开源解决方案也可以适合这里,只要该平台符合上面列出的四个要求。
虽然许多人认为 Hudi 只是一种开放式表格格式,但这是一种误解。实际上, Hudi 也是一个全面的开放湖仓一体平台,它将独特的存储引擎功能与强大的表格格式(如 Apache Parquet)开放文件格式集成在一起。与独立的表格格式不同,Hudi 提供原生功能,包括用于数据摄取、恢复、回滚和合规性跟踪的工具和实用程序。这使得 Hudi 不仅仅是湖仓一体架构的一个组件,也就是说,不仅仅是一个表格格式;它是一个强大的平台,支持广泛的分析工作负载。
下面是典型数据库管理系统的参考图,显示了 Hudi 如何构成针对湖泊环境优化的数据库的下半部分。在 Hudi 上方显示了 Hudi 与各种分析工具的集成。
Hudi 的事务层功能类似于数据库内核,通过其表格式管理文件布局和架构,并使用其时间线跟踪更改。此时间线(Log Manager 的一部分)充当关键事件日志,按顺序记录所有表操作,从而启用时间旅行、版本回滚和增量处理等功能。在性能优化方面,Hudi 利用各种索引(Access Methods 块的一部分)来最小化 I/O 并提高查询速度;这些索引包括文件列表、Bloom 筛选条件和记录级索引,它们共同促进了更快的写入和高效的查询规划。Hudi 的内置开放表服务(复制和加载服务的一部分)——例如聚簇、压缩和清理——旨在保持表存储布局的性能,能够根据操作要求以内联、半异步或完全异步模式运行。
为了处理多个并发工作负载,Hudi 使用了各种并发控制技术(Lock Manager 的一部分),例如用于写入器和表服务以及表服务之间的非阻塞多版本并发控制 (MVCC),以及用于多个写入器的乐观并发控制 (OCC),同时引入非阻塞并发控制 (NBCC) 以支持多个写入器而不会发生冲突,确保操作不会相互干扰。此外,我们还在将多租户缓存层(Buffer Manager 的一部分)与 Hudi 的事务存储集成,以平衡快速数据写入与最佳查询性能,从而实现跨查询引擎的共享缓存并降低存储访问成本。
此外,Hudi 将平台服务集成到其开放堆栈中,以管理摄取、目录同步、数据质量检查和表导出等任务。Hudi Streamer 是 Hudi 栈中原生可用且常用的摄取工具,它与 Kafka 流无缝集成,并支持自动检查点管理、架构注册表集成和重复数据删除。它还有助于回填、使用 Spark/Flink 进行连续模式操作以及增量导出。此外,Hudi 还提供了各种目录同步工具,可将 Hudi 表与各种目录(如 Hive Metastore、AWS Glue 和 Google BigQuery)同步。
图 12 显示了使用 Hudi 平台的开放式湖仓一体架构的参考实现。
从摄取端开始, Hudi Streamer 将数据从 Kafka 流、数据库或文件系统等各种来源摄取到 Hudi 中。在此架构中,Amazon S3 充当数据湖存储,保存写入记录的 Parquet 数据文件。
Apache Hudi 的表格格式在这里被用作开放表格格式的主要选择,但该架构还集成了 XTable 以确保不同格式之间的互操作性。这种灵活性允许用户在格式之间切换,并使用他们选择的计算引擎读取特定的表格式元数据。这样,他们就不会被迫坚持使用特定的表格格式或计算引擎。
Hudi 的存储引擎负责表管理服务,例如聚簇、压缩和清理旧版本的数据,同时控制存储成本。Hudi 的平台服务包括目录同步工具,这些工具可促进各种目录(如 AWS Glue 和 Hive)的数据可用性,从而支持通过 Trino 和 Presto 等交互式引擎进行查询。一旦数据可供查询,分析层中的各种工具就可以使用它,以运行从 BI 到机器学习的各种分析工作负载。
在这一点上,我们可以回答最后一个问题 - 我们如何无缝地跨不同平台移动?
我们参考架构的一个重要方面是所有组件和服务都是开放的、模块化的和可互操作的。这种灵活性可确保将来需要根据特定使用案例在平台之间切换或移动时,没有固有的限制。此架构中的用户可以选择最适合其需求的工具和服务,从而确保与其运营目标最佳一致。通过致力于开放标准并确保关键组件(数据文件格式、数据表格式、数据目录)之间的互操作性,这种方法为真正的开放式数据架构奠定了坚实的基础。
回顾
当我们回顾上面提出的问题时,很明显简单地采用开放表格格式并不能保证整体开放性。真正的开放性取决于对开放标准、互操作性和跨表格格式扩展的全面平台服务的承诺。我们了解到,虽然开放式表格格式为构建开放式架构提供了基础元素,但开放式湖仓一体平台不仅仅局限于元数据层,还包括摄取、计算引擎、存储引擎和目录等内容,所有这些都需要开放,以便跨多个环境访问数据,而不仅仅是局限于单个供应商的平台。在不同平台之间移动而不中断的灵活性对于现代数据架构至关重要。这就是为什么 Lakehouse 架构的各个组件内的互操作性起着关键作用的原因。
推荐阅读