随着大数据存储和处理需求的多样化,如何构建一个统一的数据湖存储,并在其上进行多种形式的数据分析成了企业构建大数据生态的一个重要方向。Netflix 发起的 Apache Iceberg 项目具备 ACID 能力的表格式成为了大数据、数据湖领域炙手可热的方向。
Apache Iceberg 是由 Netflix 开发开源,并于 2018年11月16日进入 Apache 孵化器。Netflix的数据湖原先是借助Hive来构建,但发现Hive在设计上的诸多缺陷之后,开始转为自研Iceberg。使用hive面临的问题如下:
总体来说,Netflix设计Iceberg的核心诉求可以归纳为如下:
Apache Iceberg 是一种用于跟踪超大规模表的新格式,是专门为对象存储(如S3)而设计的。具备如下能力:
Apache Iceberg同时支持Apache Flink的DataStream API和Table API,以将记录写入Iceberg表。目前,集成了iceberg和apache flink 1.11.x。支持的功能如下所示:
iceberg使用Apache Spark的DataSourceV2 API实现数据源和目录实现。Spark DSv2是一个不断发展的API,在Spark版本中提供了不同级别的支持:
Trino是一个基于内存的MPP计算引擎,通过并行+内存的计算方式,可以大大提高计算速度,再加上一些优化(例如剪枝、谓词下推等),就可以达到大数据量计算任务下的秒级响应。通过在trino中配置iceberg connector可以操作iceberg表。
如图所示是iceberg的表结构,其中相关概念如下所述:
存储当前版本的元数据信息(所有snapshot信息)。
快照文件,也成为清单列表文件,是以avro 格式进行存储,以 snap- 开头的。每次更新都会产生一个清单列表文件,代表一张表在某个时刻的状态。Snap*.avro里面存储的是清单文件的列表,每个清单文件占据一行。每行中存储了清单文件的路径、清单文件里面存储数据文件的分区范围、增加了几个数据文件、删除了几个数据文件等信息。这些信息可以用来在查询时提供过滤。
清单文件其实是元数据文件,其里面列出了组成某个快照(snapshot)的数据文件列表。每行都是每个数据文件的详细描述,包括数据文件的状态、文件路径、分区信息、列级别的统计信息(比如每列的最大最小值、空值数等)、文件的大小以及文件里面数据的行数等信息。其中列级别的统计信息在 Scan 的时候可以为算子下推提供数据,以便可以过滤掉不必要的文件。
清单文件是以 avro 格式进行存储的,所以是以 .avro 后缀结尾的,比如 d5ba704c-1453-4f18-9077-6944baa1b3f2-m0.avro
每次更新会产生一个或多个清单文件。
数据文件(data files)是 Apache Iceberg 表真实存储数据的文件,一般是在表的数据存储目录的 data 目录下。如果我们的文件格式选择的是 parquet,那么文件是以 .parquet 结尾,
比如 00000-0-0eca9076-9c03-4077-baa9-e68769e15c58-00001.parquet 就是一个数据文件。
核心思想:在时间轴上跟踪表的所有变化
快照隔离
Iceberg提供了表级别的抽象接口,自己在文件中维护表的元数据信息(而非通过HMS维护)。上图中,在HMS元数据存储的是iceberg表的入口信息。即iceberg表的当前版本的元数据入口路径信息。在实际应用中,如下图所示,表order的元数据信息存放在HMS上,存放的信息内容metadata_location= hdfs://node1:9000/user/hive/warehouse/orders/metadata/00009-7aa28ddf-34fe-496b-8888-3b806a8edb7a.metadata.json 是order表当前快照元信息入口。previous_metadata_location是上一个快照信息的入口。