Flink + Iceberg + 对象存储,构建数据湖方案

2021-07-14  本文已影响0人  Flink中文社区

本文整理自 Dell 科技集团高级软件研发经理孙伟在 4 月 17 日 上海站 Flink Meetup 分享的《Iceberg 和对象存储构建数据湖方案》,文章内容为:

  1. 数据湖和 Iceberg 简介
  2. 对象存储支撑 Iceberg 数据湖
  3. 演示方案
  4. 存储优化的一些思考

一、数据湖和 Iceberg 简介

1. 数据湖生态

img

如上图所示,对于一个成熟的数据湖生态而言:

2. 结构化数据在数据湖上的应用场景

img

上图为一个典型的数据湖上的应用场景。

数据源上可能会有各种数据,不同的数据源和不同格式。比如说事物数据,日志,埋点信息,IOT 等。这些数据经过一些流然后进入计算平台,这个时候它需要一个结构化的方案,把数据组织放到一个存储平台上,然后供后端的数据应用进行实时或者定时的查询。

这样的数据库方案它需要具备哪些特征呢?

Iceberg 数据库的定位就在于实现这样的功能,于上对接计算平台,于下对接存储平台。

3. 结构化数据在数据湖上的典型解决方案

img

对于数据结构化组织,典型的解决方式是用数据库传统的组织方式。

如上图所示,上方有命名空间,数据库表的隔离;中间有多个表,可以提供多种数据 Schema 的保存;底下会放数据,表格需要提供 ACID 的特性,也支持局部 Schema 的演进。

4. Iceberg 表数据组织架构

img

接下来具体看一下 Iceberg 是如何将数据组织起来的。如上图所示:

5. Iceberg 写入流程

img

上方为 Iceberg 数据写入的流程图,这里用计算引擎 Flink 为例。

6. Iceberg 查询流程

img

上方为 Iceberg 数据查询流程。

这里可以看到一个特点,就是在整个数据的查询过程中没有用到任何 List,这是因为 Iceberg 完整地把它记录好了,整个文件的树形结构不需要 List,都是直接单路径指向的,因此查询性能上没有耗时 List 操作,这点对于对象存储比较友好,因为对象存储在 List 上面是一个比较耗资源的操作。

7. Iceberg Catalog 功能一览

Iceberg 提供 Catalog 用良好的抽象来对接数据存储和元数据管理。任何一个存储,只要实现 Iceberg 的 Catalog 抽象,就有机会跟 Iceberg 对接,用来组织接入上面的数据湖方案。

img

如上图所示,Catalog 主要提供几方面的抽象。

这样可以提供灵活的操作空间,方便对接各种底下的存储。

二、对象存储支撑 Iceberg 数据湖

1. 当前 Iceberg Catalog 实现

目前社区里面已经有的 Iceberg Catalog 实现可分为两个部分,一是数据 IO 部分,二是元数据管理部分。

img

如上图所示,其实缺少面向私有对象存储的 Catalog 实现,S3A 理论上可以接对象存储,但它用的是文件系统语义,不是天然的对象存储语义,模拟这些文件操作会有额外的开销,而我们想实现的是把数据和元数据管理全部都交给一个对象存储,而不是分离的设计。

2. 对象存储和 HDFS 的比较

这里存在一个问题,在有 HDFS 的情况下,为什么还要用对象存储?

如下所示,我们从各个角度将对象存储和 HDFS 进行对比。

img

总结下来,我们认为:

下面对两个存储各自的优势进行简单阐述。

1)比较之:集群扩展性

img

2)比较之:小文件友好

img

如今在大数据应用中,小文件越来越常见,并逐渐成为一个痛点。

3)比较之:多站点部署

img

4)比较之:低存储开销

img

3. 对象存储的挑战:数据的追加上传

img

在 S3 协议中,对象在上传时需要提供大小。

以 S3 标准为例,对象存储跟 Iceberg 对接时,S3 标准对象存储不支持数据追加上传的接口,协议要求上传文件时提供文件大小。所以在这种情况下,对于这种流式的 File IO 传入,其实不太友好。

1)解决方案一:S3 Catalog 数据追加上传 - 小文件缓存本地/内存

img

对于一些小文件,流式传入的时候就写入到本地缓存 / 内存,等它完全写完后,再把它上传到对象存储里。

2)解决方法二:S3 Catalog 数据追加上传 - MPU 分段上传大文件

img

对于大文件,会用到 S3 标准定义的 MPU 分段上传。

它一般分为几个步骤:

MPU 有优点也有缺点:

4. 对象存储的挑战:原子提交

img

下一个问题是对象存储的原子提交问题。

前面提到在数据注入的过程中,最后的提交其实分为几步,是一个线性事务。首先它要读到当前的快照版本,然后把这一次的文件清单合并,接着提交自己新的版本。这个操作类似于我们编程里常见的 “i=i+1”,它不是一个原子操作,对象存储的标准里也没有提供这个能力。

img

上图是并发提交元信息的场景。

这是一个典型的冲突场景,这里需要一套机制,因为如果它不能检测到自己是一个冲突的情况的话,再提交 v007 会把上面 v007 覆盖,会导致上一次提交的所有数据都丢失。

img

如上图所示,我们可以使用一个分布式锁的机制来解决上述问题。

这是通过锁来解决并发提交的问题。

5. Dell EMC ECS 的数据追加上传

img

基于 S3 标准的对象存储和 Iceberg 问题的解决方案存在一些问题,例如性能损失,或者需要额外部署锁服务等。

Dell EMC ECS 也是个对象存储,基于这个问题有不一样的解答,它基于 S3 的标准协议有一些扩展,可以支持数据的追加上传。

它的追加上传与 MPU 不同的地方在于,它没有分块大小的限制。分块可以设置得比较小一点,上传后内部就会串联起来,依然是一个有效的文件。

追加上传和 MPU 这两者可以在一定程度上适应不同的场景。

MPU 有加速上传能力,追加上传在速度在不是很快的情况下,性能也是足够用,而且它没有 MPU 的初始化和合并的操作,所以两者在性能上能够适应不同场景进行使用。

6. Dell EMC ECS 在并发提交下的解决方案

img

ECS 对象存储还提供了一个 If-Match 的语义,在微软的云存储以及谷歌的云存储上都有这样一个接口能力。

这个实现是和锁机制一样的效果,不需要外部再重新部署锁服务来保证原子提交的问题。

7. S3 Catalog - 统一存储的数据

img

回顾一下,上方我们解决了文件 IO 中上传数据 IO 的问题,和解决了元数据表格的原子提交问题。

解决这些问题以后,就可以把数据以及元数据的管理全部都交到对象存储,不再需要额外部署元数据服务,做到真正统一数据存储的概念。

三、演示方案

img

如上所示,演示方案用到了 Pravega,可以简单理解为 Kafka 的一个替代,但是对它进行了性能优化。

在这个例子中,我们会把数据注入 Pravega 的流里,然后 Flink 会从 Pravega 中读出数据进行解析,然后存入 Iceberg 组织。Iceberg 利用 ECS Catalog,直接对接对象存储,这里面没有任何其他部署,最后用 Flink 读出这个数据。

四、存储优化的一些思考

img

上图为当前 Iceberg 支持的数据组织结构,可以看到它直接 Parquet 文件存在存储里面。

我们的想法是如果这个湖跟元数据的湖其实是一个湖,有没有可能生成的 Parquet 文件跟源文件存在很大的数据冗余度,是否可以减少冗余信息的存储。

比如最极端的情况,源文件的一个信息记录在 Iceberg 中,就不存这个 Parquet 数据文件。当要查询的时候,通过定制 File IO,让它根据原文件在内存中实时生成一个类似于 Parquet 的格式,提交给上层应用查询,就可以达到一样的效果。

但是这种方式,局限于对存储的成本有很高的要求,但是对查询的性能要求却不高的情况。能够实现这个也要基于 Iceberg 好的抽象,因为它的文件元数据和 File IO 都是抽象出来的,可以把源文件拆进去,让它以为这是一个 Parquet 文件。

进一步思考,能否优化查询性能,同时节省存储空间。

比如预计算一下,把源文件某些常用的列拿出来,然后统计信息到 Iceberg 中,在读的时候利用源文件和云计算的文件,可以很快查询到信息,同时又节省了不常用的数据列存储空间。

这是比较初步的想法,如果能够实现,则用 Iceberg 不仅可以索引结构化的 Parquet 文件格式,甚至可以索引一些半结构化、结构化的数据,通过临时的计算来解决上层的查询任务,变成一个更完整的 Data Catalog。

上一篇 下一篇

猜你喜欢

热点阅读