Apache Iceberg简介

Apache Iceberg是一种相对较新的开放表格式,专为巨大的PB级表而设计。表格式的功能是决定如何管理、组织和跟踪所有组成表格的文件。我们可以把它看作物理数据文件(用Parquet或ORC等写的)和它们如何被构造成表之间的抽象层。

使用保存在每个表上的大量元数据,Iceberg提供了其他表格式通常无法提供的功能。这包括模式演化、分区演化和表版本回滚—所有这些都可以在不需要代价高昂的表重写或表迁移的情况下实现。

该项目最初是由Netflix公司开发的,目的是解决他们使用巨大的PB级表的长期问题。它于2018年作为Apache孵化器项目开源,并于2020年5月19日从孵化器中毕业。

Apache Iceberg设计的一个关键考虑是解决各种数据一致性和性能问题,这些问题是Hive在使用大数据时所面临的问题。Hive在“文件夹”级(即不是文件级)跟踪数据,因此在处理表中的数据时需要执行文件列表操作。当需要执行其中许多操作时,这可能会导致性能问题。当在最终一致的对象存储(如S3)上执行文件列表操作时,还可能出现数据丢失的情况。Apache Iceberg通过使用持久树结构跟踪表中所有文件的完整列表来避免这种情况。对表的更改使用原子对象/文件级提交将路径更新到一个新的元数据文件,该元数据文件包含所有单独数据文件的位置。

Apache Iceberg 具有以下特色功能:

  • (1) 模式进化(Schema evolution)。支持添加、删除、更新或重命名,并且没有副作用。
  • (2) 隐藏分区(Hidden partitioning)。防止因用户失误导致的无提示错误结果或极慢的查询。
  • (3) 分区布局演变(Partition layout evolution)。可以随着数据量或查询模式的变化更新表的布局。
  • (4) 时间旅行(Time travel)。支持使用完全相同的表快照进行重复查询,或让用户轻松检查更改信息。
  • (5) 版本回退(Version rollback)。允许用户通过将表重置为之前某一时刻的状态来快速纠正问题。

关于可靠性与性能方面,Apache Iceberg 适用于查询大型表格,其中单个表可以包含数十 PB 的数据,甚至可以在没有分布式 SQL 引擎的情况下读取它们,并且旨在解决最终一致的云对象存储中的正确性问题:

  • (1) 快速的扫描计划:不需要分布式 SQL 引擎来读取表或查找文件。
  • (2) 高级过滤:使用表元数据、分区和列级统计信息修剪数据文件。
  • (3) 通过避免监听和重命名,适用于任何云存储并在HDFS中减少NameNode拥塞。
  • (4) 可序列化隔离:表更改是原子的,读取时不会看到部分或未提交的更改。
  • (5) 利用乐观锁控制并发写入,并会重试以确保兼容更新成功。

有关存储格式方面,Apache Iceberg 中的一些概念列举如下:

  • (1) 分区规范(Partition spec):定义了如何从数据文件推断分区信息。
  • (2) 快照(Snapshot):表在某个时刻的状态,由清单列表定义。每个快照都列出了在快照时构成表内容的所有数据文件。
  • (3) 清单列表(Manifest list):列出组成表快照的清单的元数据文件,这是Avro格式文件。清单列表中的每个清单文件都存储了关于其内容的信息,比如分区值范围,以加快元数据操作。
  • (4) 清单文件(Manifest):列出组成快照的数据文件子集的元数据文件,这也是Avro 格式文件。清单中的每个数据文件都存储有分区元组、列级统计信息和摘要信息,这些信息用于在扫描规划期间修剪分裂。
  • (5) 数据文件(Data file)。真实存储数据的文件。

在Apache Spark 3中可以多种方式使用Iceberg。下面列出了其中常用的几种方法。

(1) 方式一,在启动spark-shell时指定。命令如下:

$ spark-shell --packages org.apache.iceberg:iceberg-spark-runtime-3.1_2.12:0.13.1

(2) 方式二,将iceberg-spark-runtime-3.1_2.12:0.13.1.jar包添加到Spark的jars目录下。

(3) 方式三,如果是使用Maven开发,则在项目的pom.xml文件中添加依赖,内容如下:

<dependency>
    <groupId>org.apache.iceberg</groupId>
    <artifactId>iceberg-core</artifactId>
    <version>0.13.1</version>
</dependency>

(4) 方式四,如果是使用SBT开发,则在项目的build.sbt文件中添加依赖,内容如下:

libraryDependencies += "org.apache.iceberg" % "iceberg-core" % "0.13.1"

《Spark原理深入与编程实战》