掌握Apache Iceberg以实现可扩展的数据湖管理
介绍
随着数据量的指数级增长,组织正在转向更加开放、灵活和可扩展的数据湖架构。但到底什么是数据湖架构呢?
数据湖架构是一种存储大量原始数据的系统,能够以其原生格式(结构化、半结构化或非结构化)进行存储,直到需要进行分析时再使用。与传统数据库不同,数据湖可以处理从实时流到批量文件的所有内容,使其非常适合大数据和机器学习工作流程。然而,传统数据湖解决方案通常伴随着一系列挑战,例如性能慢、管理模式变化困难以及与特定处理引擎的紧密耦合。这就是Apache Iceberg发挥作用的地方。
Apache Iceberg 是一种现代的开源表格式,旨在克服与传统数据湖相关的许多常见痛点。凭借其强大的元数据处理能力、内置的模式演变支持以及与 Apache Spark 和 Flink 等多种处理引擎的兼容性,Iceberg 正在改变团队管理和分析大数据的方式。在本指南中,我们将深入了解 Apache Iceberg 的概念,探索其关键特性和架构,并分享一些在您的环境中实施它的实用建议。我们还将回答关于处理模式演变和将 Iceberg 与 Apache Spark 等引擎集成的常见问题,以便您能够顺利启动和运行。
先决条件
- 对Apache Spark和Hive或类似分布式计算平台的熟悉程度。
- 了解数据湖架构。这包括文件格式(如Parquet和ORC)、存储系统(例如HDFS和S3)以及分区策略的知识。
- 能够编写SQL查询并创建表,同时执行诸如INSERT、UPDATE和ALTER等操作。
- 确保安装并运行 Apache Spark 3.x,同时安装与您的 Spark 版本相应的 Iceberg 运行时包。
- 配置 Hive Metastore、AWS Glue 系统或兼容目录,以管理 Iceberg 表元数据。
什么是 Apache Iceberg?
Apache Iceberg 是一种开源表格格式,用于管理大型分析数据集。它由 Apache 软件基金会开发,旨在应对在数据湖中存储和查询大量数据所面临的挑战。Iceberg 背后的团队旨在创建一种更可靠、一致和高效的方式来管理表元数据、跟踪文件位置和管理模式变化。随着越来越多的组织使用云数据湖来管理海量数据集,这一点尤为重要。
Apache Iceberg的主要特点
Apache Iceberg 的基本特征凸显了它为何成为管理大数据的首选标准。
模式演变 Iceberg 支持表模式演变,允许在不更改现有数据文件的情况下添加、删除、重命名或重新排序列。它通过为每一列分配一个唯一的 ID 并在元数据中跟踪模式变化来实现这一点。
分区和分区演变 Iceberg 表通过一个或多个键(如日期、类别等)支持分区,以提高查询性能。Iceberg 提供对隐藏分区和分区演变的独特支持。隐藏分区允许表内部跟踪分区值。这使得查询引擎能够在无需用户干预的情况下,自动进行分区剪裁,从而添加分区过滤器。
格式无关冰山可以处理各种文件格式,尽管它通常与Parquet相关,以支持不同的数据摄取策略。
ACID 事务 Iceberg 确保数据湖操作中的事务安全,这提供了在数据仓库和高级事务系统中常见的 ACID 属性。
时间旅行和数据版本控制 每个冰山快照都会被保留,直到你主动选择使其过期。时间旅行查询可以访问任意先前快照或时间戳的表数据。例如,您可以运行以下命令,
*SELECT * FROM my_table*
*FOR TIMESTAMP AS OF '2025-01-01 00:00:00*'
查看您2025年初的数据。
性能优化
Iceberg 是为大数据性能而构建的。包含清单的元数据树使 Iceberg 能够通过修剪不必要的文件和分区来避免对整个表的扫描,以满足特定查询的需求。
Apache Iceberg 架构:它是如何工作的?
从高层次来看,Apache Iceberg 架构由几个关键组件组成:
元数据层:该层由多个文件组成,这些文件维护着关于表的结构和状态的综合信息。
- 元数据文件 (metadata.json):此文件跟踪当前架构、分区规格、快照以及对最近快照的清单列表的引用。
- 清单列表:它指向相关的清单文件,随时提供表的可靠快照。
- 清单文件:包含数据文件列表和统计信息,如记录数量、列的最小/最大值以及每个文件的元数据。
数据层:此层包含实际的数据文件。它使用列式格式(例如 Parquet、ORC 和 Avro)存储数据。
当在 Iceberg 表上执行查询时,系统会遵循以下步骤:
- 元数据检索: 查询引擎从目录中检索当前的 metadata.json 文件。
- 快照识别: 它查看最新的快照或特定的快照,如果我们使用时间旅行功能的话。
- 清理清单: 查询引擎扫描清单列表,通过查询谓词删除不相关的清单文件。
- 数据访问: 系统读取由相关清单文件指定的必要数据文件,并应用过滤器以提取所需的数据。
比较:Apache Iceberg vs. Hudi vs. Delta Lake
冰山(Iceberg)常常与其他开放式表格格式如Apache Hudi和Delta Lake进行比较。这三者都旨在为数据湖带来ACID事务和可靠性,但在方法和功能上有所不同。
| 特征 | 阿帕奇冰山 | 阿帕奇 Hudi | 德尔塔湖 |
|---|---|---|---|
| 核心原则 | 通过快照和清单进行元数据跟踪 | MVCC,索引,时间线 | 交易日志(JSON 操作) |
| 建筑 | 不可变的元数据层 | 写入优化(写时复制/读时合并) | 已排序的提交日志 |
| 架构演变 | 强,无需重写(添加、删除、重命名等) | 支持,但可能需要类型兼容性 | 支持,类似于冰山 |
| 分区演变 | 是的,透明地 | 更复杂,可能需要补充材料 | 需要重新编写表格(截至目前的开源版本) |
| 隐藏的分区 | 是的 | 不(需要明确的分区列) | 生成的列(类似) |
| 时间旅行 | 是的(基于快照) | 是的(基于即时) | 是的(基于版本) |
| 更新/删除 | 写时复制(默认),读时合并(计划中) | 写时复制和读时合并(成熟) | 写时复制(通过合并) |
| 索引 | 依赖于统计和分区 | 布隆过滤器,哈希索引 | 依赖于统计信息、分区、Z-Ordering(Databricks) |
| 主要引擎 | Spark,Flink,Trino,Hive,Dremio | Spark, Flink, Hive | Spark(主要),存在Trino/Presto/Hive连接器 |
| 开放性 | Apache许可证,完全开放的规范 | Apache许可证,完全开放的规范 | Linux基金会;核心开放,部分功能以Databricks为中心 |
主要差异总结:
- 冰山:它强调独立于元数据,允许强大的架构和分区演变,并通过统计数据提供令人印象深刻的修剪。它在不同的引擎之间具有适应性。
- Hudi: 提供对按需合并的成熟支持,非常适合快速更新和插入更新。它还支持内置索引功能。然而,设置可能有些复杂。
- Delta Lake: 它与 Spark(特别是在使用 Databricks 时)有很强的集成,并在一个简单的事务日志系统上运行。开源版本不支持 Databricks 运行时的一些高级功能,如分区演变和高级 Z 排序。
在选择 Iceberg、Hudi 或 Delta Lake 之间时,应根据特定的使用案例、您当前的技术环境和优先功能(例如,更新频率与模式灵活性)来决定。
实施 Apache Iceberg
我们将展示如何使用 Apache Iceberg 与 Spark(通过 Spark SQL)来创建和管理 Iceberg 表。Apache Iceberg 通过其 DataSource V2 API 实现与 Spark 的无缝集成。这使得用户在适当配置后,可以运行标准的 Spark SQL 命令来管理 Iceberg 表。
Apache Iceberg 的先决条件
- 确保您安装的是 Spark 3.x: 您的第一步应该是验证您的计算机上是否安装了 Spark 3.x.
- 冰山火花运行包: 获取与您的 Spark 和冰山版本号相对应的冰山连接器 JAR 文件。
- 在 Spark 中包含 JAR: 在启动 Spark 时(通过 spark-shell 或 spark-sql),将 Iceberg 连接器 JAR 包含在您的类路径中。要包含其他包或依赖项,可以使用 --packages 选项。
使用此命令启动 Spark-SQL,版本为 Iceberg 1.2.1 和 Spark 3.3。
spark-sql --packages
org.apache.iceberg:iceberg-spark-runtime-3.3_2.12:1.2.1
--packages org.apache.iceberg:iceberg-spark-runtime-3.3_2.12:1.2.1: 此选项指示与 Spark 3.3 和 Scala 2.12 兼容的 Iceberg 运行时包的 Maven 坐标,版本为 1.2.1。您可以在 Maven 中央仓库中找到此包。
步骤 1:为 Iceberg 配置 Spark 目录
要配置 Spark 使用 Iceberg 的目录,您可以在 spark-defaults.conf 文件中进行配置,或通过命令行 --conf 选项进行配置。以下是一个示例:
spark-sql \
--packages org.apache.iceberg:iceberg-spark-runtime-3.3_2.12:1.2.1 \
--conf spark.sql.catalog.local=org.apache.iceberg.spark.SparkCatalog \
--conf spark.sql.catalog.local.type=hadoop \
--conf spark.sql.catalog.local.warehouse=/tmp/iceberg_warehouse \
--conf spark.sql.extensions=org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions
- spark.sql.catalog.local:这建立了一个名为 local 的 Spark 目录,使用 Iceberg 的 SparkCatalog。
- spark.sql.catalog.local.type=hadoop: 此设置指示 Iceberg 在与 Hadoop 兼容的文件系统中处理元数据。
- spark.sql.catalog.local.warehouse:指定仓库目录(例如,/tmp/iceberg_warehouse)。
- spark.sql.extensions:这使得一些特定于 Iceberg 的 SQL 扩展(例如,合并、删除)可以使用。
在本地目录下创建的表将保存在定义为您的仓库路径的目录中。注意: 您必须首先配置目录;否则,Spark可能只是默认创建一个Hive表。
步骤2:创建冰山表并插入数据
我们来创建一个示例冰山表并插入一些记录:
CREATE TABLE local.learning.employee (
id INT,
name STRING,
age INT
)
USING iceberg;
-- Insert records into the table
INSERT INTO local.learning.employee VALUES
(1, 'Adrien', 29),
(2, 'Patrick', 35),
(3, 'Paul', 41);
通过上述命令,我们在本地目录的学习命名空间中创建了一个员工表。使用 Iceberg子句告诉 Spark 使用 Iceberg 数据源,这对于正确管理表非常重要。该表的所有数据和元数据将存储在指定的仓库目录中,作为一个 Iceberg 目录。
步骤3:执行更新和架构演变
假设我们想要更新员工记录中的一项(更改Patrick的名字),并且还想添加一列来跟踪电子邮件地址。我们可以使用SQL UPDATE和ALTER TABLE语句在Iceberg中实现这一点。
-- Update Patrick's name to Flobert
UPDATE local.learning.employee
SET name = 'Flobert'
WHERE id = 2;
-- Alter the table to add a new email column
ALTER TABLE local.learning.employee
ADD COLUMNS (email STRING);
-- Insert a new record that includes the new email field
INSERT INTO local.learning.employee VALUES
(4, 'David', 30, 'david@company.com')
在背景中:
- 更新 操作: 它为分区生成了一个新的数据文件,包含Patrick的更新名称。同时,它还在元数据中将旧文件部分标记为已删除。
- 修改表操作:ALTER TABLE ADD COLUMNS 在元数据中更新了表的架构,并为电子邮件列分配了一个新 ID,而没有修改现有文件。
- 插入操作: 该操作插入了大卫的记录,包括新的 电子邮件 字段。
这种方法使我们能够高效地处理模式变更,并尽量减少对昂贵表重写的需求。
在Apache Iceberg中处理大规模元数据
冰山通过有效管理元数据展示了出色的性能:
- 清单文件: Iceberg将元数据分割成较小的清单文件,而不是一个含有所有数据的巨大文件,每个清单文件描述数据的子集。
- 并行操作:这种设计使查询能够跳过整个元数据文件,仅读取相关的分区或子集。
- 分区修剪:Iceberg 在文件级别跟踪最小/最大统计信息,允许它修剪不符合查询条件的分区或数据文件。
这种策略在处理包含数百万个数据文件的环境中变得至关重要。它消除了扫描大型元数据文件的需要,并避免了每当新数据到达时复杂的重写过程。
多云环境中的Apache Iceberg
如今,组织通过使用来自AWS、Azure和Google Cloud的服务在多个云平台上运作。Apache Iceberg独立于对象存储系统运作。它将允许您:
- 将数据存储到主要云平台提供的对象存储服务(如 S3、GCS 和 ADLS)中。
- 通过集中式Hive Metastore系统、AWS Glue目录或其他目录处理表元数据。
- 在您选择的任何云平台上执行 Spark 或 Presto,以访问相同的 Iceberg 表进行读取和写入操作。
这种灵活性帮助您避免被锁定在一个提供商身上,同时利用每个云的优势——更好的计算折扣、先进的人工智能服务,或根据您的地区的合规特性。
处理架构演变问题
复杂模式演变的强大特性带来了一些挑战。下表呈现了Apache Iceberg模式演变的主要考虑因素。
| 方面 | 描述 | 推荐 |
|---|---|---|
| 读者/写者兼容性 | 表格必须能够被支持所用架构特性的引擎读取。较旧的 Spark 版本可能不支持较新的 Iceberg 规范特性。 | 在应用架构更改之前,始终测试升级。 |
| 复杂类型更改 | 简单的提升是安全的,但复杂的更改(例如,修改 struct 字段或 map 键/值)需要仔细测试。 | 严格遵循Iceberg的架构演变指南。 |
| 下游消费者 | 使用 Iceberg 表的应用程序和 SQL 查询必须处理模式更改。重命名列可能会导致下游查询出错。 | 确保在架构变更后,下游系统得到更新和测试。 |
| 性能影响 | 模式演化不会重写数据,但可以随着频繁或复杂的变化而扩展元数据。在某些情况下,性能可能会受到影响。 | 如有需要,定期进行维护或可选的压缩以优化。 |
团队应该逐步实施更新,对所有使用引擎进行全面测试,并利用Iceberg的元数据历史记录来跟踪变化。
与Spark或Hive集成的Apache Iceberg故障排除
本节介绍了在将 Apache Iceberg 与 Spark 或 Hive 集成时常见的问题。您可以逐一查看这些问题,并在必要时查阅官方文档:
| 问题 | 描述 | 推荐 |
|---|---|---|
| 版本冲突 | 不匹配的 Spark 和 Iceberg 版本可能导致类未找到或未定义的方法错误。 | 确保您的Spark和Iceberg版本兼容。 |
| 目录配置 | 冰山需要一个目录(Hive、Glue、Nessie)来管理元数据。 | 在您的引擎配置中设置正确的URI和凭据。 |
| 权限错误 | 在像HDFS或云存储这样的文件系统上可能会出现读写权限问题。 | 验证您的引擎是否拥有对文件系统的适当访问权限。 |
| 检查点或快照问题 | 在流式处理中手动删除或损坏快照可能会导致失败。 | 避免手动编辑;如有需要,请恢复到稳定快照。 |
频繁检查集成系统和日志可以及早发现冲突。这将有助于保持顺利的操作,同时减少停机时间。
常见问题
什么是Apache Iceberg?
Apache Iceberg 是一种开源表格式,旨在管理大规模分析数据集。Apache Iceberg 就像是大数据湖中存储的大数据的智能整理者。
当您在云存储或HDFS中存储大量数据(如Parquet或ORC文件)时,管理可能会变得混乱且困难,尤其是在数据不断变化或增长的情况下。Iceberg帮助以结构化、高效和可靠的方式组织这些数据,以便像Apache Spark、Flink和Trino这样的工具可以更快、更准确地处理这些数据。
将冰山视为一种表格格式,有点像Excel如何以行和列来组织数据。但与传统格式不同的是,冰山能够轻松跟踪元数据(关于数据的数据)、支持模式变更,并允许像时间旅行(查看数据的过去版本)、增量读取和ACID事务(以确保数据的一致性)这样的功能。
Apache Iceberg 如何提高数据湖的性能?
Iceberg通过在更紧凑的清单中存储元数据来提高性能,从而实现有效的分区裁剪。该系统通过将查询限制在相关的清单和数据文件上来优化性能,从而最小化I/O开销。快照在读取和写入期间实现一致的数据访问,同时防止与并发相关的问题。
Iceberg 如何处理模式演变?
模式演变是基于版本的。每当您修改模式时,Iceberg 会生成一个新的快照指向更新后的模式。旧的快照保持不变,因此对以前数据的查询仍然有效,而无需重写任何历史文件。
Apache Iceberg、Delta Lake 和 Hudi 之间有什么区别?
- Iceberg 强调与引擎无关的元数据管理,并优化大规模数据的性能。
- Delta Lake 关注ACID事务,与Databricks紧密合作,并允许时间旅行查询。
- Hudi 被设计为增量处理数据,并通过其先进的更新插入功能支持近实时分析。
我可以在Apache Spark中使用Apache Iceberg吗?
绝对可以!Apache Iceberg 可以与 Spark 集成,使得通过 Spark SQL 或 DataFrame API 轻松读取、写入和管理 Iceberg 表。
在数据湖中使用 Apache Iceberg 的主要好处是什么?
在数据湖中使用Apache Iceberg的一些主要好处包括支持ACID事务、轻量但强大的元数据管理、快照隔离、平滑的模式演变以及不同引擎之间的兼容性。
Apache Iceberg 最常见的使用案例是什么?
Apache Iceberg 可以处理各种数据管理任务。这包括批量分析、增量数据处理、卸载数据仓库任务、支持机器学习特征库以及管理物联网数据。
结论
Apache Iceberg 正在成为组织处理现代数据湖所面临挑战的首选技术。它开放且可扩展的设计与不同的引擎兼容,使数据团队能够自由管理模式变化、解决性能问题并维护一致性。
Apache Iceberg 为单云和多云环境中的高性能数据湖奠定了基础。使用本指南中的最佳实践和故障排除提示,将帮助您最大化 Iceberg 在数据分析需求中的能力。
为了加深你对基于Apache的技术及其如何融入各种基础设施的理解,请查看以下文章:
在 Ubuntu 22.04 上安装 Apache 网络服务器的指南
- Apache与Nginx:你需要知道的事
- 在Ubuntu上使用Let's Encrypt保护Apache
- 解决常见的Apache错误
虽然这些资源主要集中在Apache HTTP服务器上,但开源协作、配置管理和系统故障排除的基本概念可以应用于您与Apache Iceberg的工作。
资源
- Apache Iceberg与Delta Lake:有什么区别?
- Apache Iceberg与Delta Lake与Apache Hudi
- 冰山表:功能、优点和最佳实践的全面指南
- Apache Iceberg — CRUD操作
- 理解 Apache Iceberg 清单文件


