数据湖学习笔记No.04(Iceberg)

Iceberg介绍

lambda

离线与实时计算的结果不一致

Kappa架构

不要离线,全部搞成实时

Kappa 架构可以称为真正的实时数仓,目前在业界最常用实现就是 Flink + Kafka,然而基于 Kafka+Flink 的实时数仓方案也有几个非常明显的缺陷,所以在目前很多企业中实时数仓构建中经常使用混合架构,没有实现所有业务都采用 Kappa 架构中实时处理实现。

架构缺陷如下:

1) Kafka 无法支持海量数据存储。对于海量数据量的业务线来说,Kafka 一般只能存储非常短时间的数据,比如最近一周,甚至最近一天。

2) Kafka 无法支持高效的 OLAP 查询,大多数业务都希望能在 DWD\DWS 层支持即席查询 的,但是 Kafka 无法非常友好地支持这样的需求。(不支持sql)

3) 无法复用目前已经非常成熟的基于离线数仓的数据血缘、数据质量管理体系。需要重新实现一套数据血缘、数据质量管理体系。(做分层不能很好的集成原有的数据血缘关系)

4) Kafka 不支持数据的删除与更新,只支持数据的append。

数据湖做到了实时数据与离线数据的统一,流数据与批数据的统一,解决了Kappa结构的痛点问题。

为了解决 Kappa 架构的痛点问题,业界最主流是采用“批流一体”方式,这里批流一体可以理解为批和流使用SQL同一处理,也可以理解为处理框架的统一,例如:Spark、Flink, 但这里更重要指的是存储层上的统一,只要存储层面上做到“批流一体”就可以解决Kappa遇到的各种问题。数据湖技术可以很好的实现存储层面上的“批流一体”,这就是为什么大数据中需要数据湖的原因。

Iceberg

Apache Iceberg 是一种用于大型数据分析场景的开放表格式(Table Format)。Iceberg 使用一种类似于 SQL 表的高性能表格式,Iceberg 格式表单表可以存储数十 PB 数据,适配 Spark、Trino、PrestoDB、Flink 和 Hive 等计算引擎提供高性能的读写和元数据管理功能,Iceberg 是一种数据湖解决方案。

轻量级的项目,可以作为lib与Spark、Flink进行集成 https://iceberg.apache.org/

1、 Iceberg 支持实时/批量数据写入和读取,支持 Spark/Flink 计算引擎。

2、 Iceberg 支持事务 ACID,支持添加、删除、更新数据。

3、 不绑定任何底层存储,支持 Parquet、ORC、Avro 格式兼容行存储和列存储。(可基于HDFS)

4、 Iceberg 支持隐藏分区和分区变更,方便业务进行数据分区策略。

5、Iceberg 支持快照数据重复查询,具备版本回滚功能。

6、 Iceberg 扫描计划很快,读取表或者查询文件可以不需要分布式 SQL 引擎。

7、Iceberg 通过表元数据来对查询进行高效过滤。

8、基于乐观锁的并发支持,提供多线程并发写入能力并保证数据线性一致。

Iceberg术语
  1. data files(数据文件):

  1. 数据文件是Iceberg表真实存储数据的文件,一般是在表的数据存储目录的data目录下,如果我们的文件格式选择的是parquet,那么文件是以“.parquet"结尾。(Iceberg每次更新产生多个数据文件)

  1. Snapshot(表快照):

  1. 快照代表一张表在某一个时刻的状态。每个快照里会列出表在某个时刻的所有data files列表。data files是存储在不同的manifest files里面,manifest files是存储在一个manifest list文件里面,而一个manifest list文件代表一个快照。

  1. Manifest list(清单列表):

  1. manifest list是一个元数据文件,它构建出快照的清单,这个元数据文件中存储的是Manifest file列表,每个manifest file占据一行。每行中存储了manifest file的路径、其存储的数据文件(data files)的分区范围、增加了几个数据文件、删除了几个数据文件等信息,这些信息可以用来在查询时提供过滤、加快速度。

  1. Manifest file(清单文件):

  1. Manifest file是一个元数据文件,它列出组成快照(snapshot)的数据文件(data files)的详细信息。每行都是每个数据文件的详细描述,包括数据文件的状态、路径信息、分区信息、列级别的统计信息(比如每列的最大最小值、空值数等)、文件的大小以及文件里面数据行数等信息。其中列级别的统计信息可以在扫描表数据时过滤掉不必要的文件。

Table Format表格式是指元数据与数据组织方式

Iceberg处于底层存储(例如HDFS)和上层计算框架(Flink、Spark)之间

Iceberg特点详述

Iceberg分区和隐藏分区(Hidden Partition)

Iceberg支持分区来加快数据查询,在其中设置分区后,可以在写入数据时将相似的行分组,在查询时加快查询速度。可以按照年、月、日和小时粒度时间戳组织分区。

与Hive相比的进步点

在 Hive 中也支持分区,但是要想使分区能加快查询速度,需要在写 SQL 时指定对应的 分区条件过滤数据,在 Iceberg 中写 SQL 查询时不需要再 SQL 中特别指定分区过滤条件, Iceberg 会自动分区,过滤掉不需要的数据。

隐藏分区

在 Iceberg 中分区信息可以被隐藏起来,Iceberg 的分区字段可以通过一个字段计算出来, 在建表或者修改分区策略之后,新的数据会自动计算所属于的分区,在查询的时候同样不用 关心表的分区是什么字段,只需要关注业务逻辑,Iceberg 会自动过滤不需要的分区数据。 正是由于 Iceberg 的分区信息和表数据存储目录是独立的,使得 Iceberg 的表分区可以被修改,而且不会涉及到数据迁移。

Iceberg表演化

在 Hive 分区表中,如果把一个按照天分区的表改成按小时分区,那么没有办法在原有 表上进行修改,需要创建一个按照小时分区的表,然后把数据加载到此表中。

Iceberg 支持就地表演化,可以通过 SQL 的方式进行表级别模式演进,例如:更改表分 区布局。Iceberg 进行以上操作时,代价极低,不存在读出数据重新写入或者迁移数据这种 费时费力的操作

模式Schema演化

ADD:向表或者嵌套结构增加新列。

Drop:从表或嵌套结构中移除列。

Rename:重命名表中或者嵌套结构中的列。

Update:将复杂结构(Struct、Map,list)中的基本类型扩展类型长度,比如: tinyint 修改成 int。

Reorder:改变列的顺序,也可以改变嵌套结构中字段的排序顺序。

只是对元数据的操作改变

1、增加列时不会从另一个列中读取已存在的数据

2、删除列或者嵌套结构中的字段时,不会改变任何其他列的值。

3、更新列或者嵌套结构中字段时,不会改变任何其他列的值。

4、 改变列或者嵌套结构中字段顺序的时候,不会改变相关联的值。

Iceberg 实现以上的原因使用唯一的 id 来追踪表中的每一列,当添加一个列时,会分配新的id。

分区演化

Iceberg分区可以在现有表中更新,因为Iceberg查询流程并不喝分区信息直接关联。

当我们改变一个表的分区策略时,对应修改分区之前的数据不会改变。老数据采取老的分区策略,新数据采取新的分区策略。

列顺序演化

Iceberg可以在一个已经存在的表上修改排序策略,修改了排序策略之后,旧数据老排序策略,新数据新的排序策略。而在Iceberg里写数据的计算引擎总会选择最新的排序策略。

Iceberg数据查询

1、查询最新快照数据

查 询 Iceberg 表 数 据 时 , 首 先 获 取 最 新 的 metadata 信 息 , 这 里 先 获 取 到 “00000-ec504.metadata.json”元数据信息,解析当前元数据文件可以拿到当前表的快照 id: “949358624197301886”以及这张表的所有快照信息,也就是 json 信息中 snapshots 数组对应的值。

根据当前表的快照 id 值可以获取对应的 snapshot 对应的 avro 文件信息: “snap--32800.avro”,我们可以找到当前快照对应的路径,看到其包含的 Manifest 清单文件有 5 个:"32800-m0.avro"、"2abba-m0.avro"、"d33de-m0.avro"、"748bf-m0.avro"、 "b946e-m0.avro",读取该 Iceberg 格式表最新数据就是读取这几个文件中描述对应的 parquet 数据文件即可。

根据 Manifest list 找到了各个对应的 manifest 清单文件,每个文件中描述了对应 parquet 文件存储的位置信息,可以看到在对应的 avro 文件中有“status”属性,该属性为 1 代表对 应的 parquet 文件为新增文件,需要读取,为 2 代表 parquet 文件被

2、查询某个快照的数据

spark.read.option("snapshot-id",6155408340798912701L).format("iceberg").load("path")

3、根据时间戳查看某个快照的数据

spark.read.option("as-of-timestamp","时间戳").format("iceberg").load("path")

我们可以看到其中有个timestamp-ms属性和snapshot-id属性 , 并且是按照timestamp-ms升序的。在 Iceberg 内部实现中,它会将 as-of-timestamp指定的时间和 snapshot-log数组里面每个元素的timestamp-ms进行比较,找出最后一个满足timestamp-ms <= as-of-timestamp对应的 snapshot-id,原理同上,通过 snapshot-id 再找到要读取的数据文件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值