摘要:本文整理自阿里云开源大数据表存储团队负责人、阿里巴巴高级技术专家,Apache Flink PMC,Paimon PPMC 李劲松(之信)在 Apache Paimon Meetup 的分享。本篇内容主要分为四个部分:
- 湖存储上的难点
- 深入 Apache Paimon 0.4
- 社会应用实践
- 后续规划
点击查看原文视频 & 演讲PPT
今年 6 月份 Paimon 0.4 刚刚发布,它是一个非常具有竞争力的版本,也是进入 Apache 孵化器之后的第一个版本。
一、湖存储上的难点
数据湖的新场景主要有以下三个:
- 第一个场景,实时数据入湖。数据可以实时更新来自数据库的 CDC 数据,实时入湖到数据湖中,让数据能被多种引擎尽快分析。
- 第二个场景,实时字段打宽。实时打宽维表的字段,提供给下游查询及流读。
- 第三个场景,实时数据流读。提供消息队列体验的流读,并能根据主键生成 Changelog。
入湖的痛点有以下三点:
-
资源消耗与实时性:更新吞吐差,资源消耗巨大;COW 更新差,MOR 查询差,难以选择反压、反压、还是反压。
-
数据湖需管理的事情多:管理 Compaction;清理历史小文件;清理过期分区。
-
Schema Evolution:上游加列,湖存储怎么办?重启同步作业?一堆小表耗资源且耗精力。
打宽表的痛点有以下三点:
-
资源消耗与实时性:吞吐和资源同样重要。
-
输入多样性:CDC 输入;输入可能是乱序的。
-
读取:希望可以足够高效,有 Project pushdown,且可以流读。
流读的痛点有以下四点:
-
全增量一体流读:先读全量再接增量,完整的流,而不是只读增量。
-
Changelog 生成:有些场景要低成本;有些场景要低时延。
-
FileNotFound:数据湖文件清理和流读的矛盾。
-
Lookup Join:支持 Flink 的 Lookup Join。
Apache Paimon 是一个专门为 CDC 处理、流计算而生的数据湖。希望带来你舒服、自动的湖上流处理体验。
从官网上也可以看到,Apache Paimon 支持高速的数据写入,Changelog 的生成以及高效的实时查询。
二、深入 Apache Paimon 0.4
Paimon 的整体架构是一个数据湖 build 在 Data Lake (HDFS/OSS/S3),它的所有 Meta 和数据都存储在这些数据湖上,它是一个数据湖格式。这个数据湖的 Meta 也可以同步到 Hive Metastore 和阿里云的 Data Lake Formation 上,做一个统一的、数据的、表格式的管理。然后数据湖通过把 Changelog 同步到入湖中,再同步 Kafka。
现在 Paimon 0.4 提供了 Flink CDC 的 Schema Evolution 同步,也提供了 MySQL 的整库同步,后续 Paimon 0.5 会支持 Kafka 的 CDC 数据同步。此外,我们还可以通过 Flink 将 Append 的 log data 通过批写的方式写入 Paimon 中,也可以通过宽表合并的方式写入 Paimon 中。
在读端,Paimon 可以支持来自各种引擎的批读和 Ad-Hoc 查询,比如 Spark、Trino、StarRocks 等,也可以通过 Flink 来全增量一体的流读它的 Changelog,而且流读是可以提供数据顺序保障的,也可以通过 Flink 来 Lookup Join。
Paimon 是数据湖+LSM 的架构,下面和大家分享一下为什么 Paimon 需要 LSM。
LSM 是一个面向写友好的格式,它在写入的时候可以看到整个流程,但它不用理解具体的流程,大致的思路是,写入发生在 Flink Sink 中,当检查点到达时,它会对内存中的数据进行排序,并将记录刷新到 Level0 文件中。
得益于 LSM 这种原生异步的 Minor Compaction,它可以通过异步 Compaction 落到最下层,也可以在上层就发生一些 Minor 的 Compaction 和 Minor 的合并,这样压缩之后它可以保持 LSM 不会有太多的 level。保证了读取 merge read 的性能,且不会带来很大的写放大。
另外,Flink Sink 会自动清理过期的快照和文件,还可以配置分区的清理策略。所以整个 Paimon 提供了吞吐大的 Append 写,消耗低的局部 Compaction,全自动的清理以及有序的合并。所以它的写吞吐很大,merge read 不会太慢。
基于 Paimon 的设计,我们一起看一下来自同程旅行的生产实践,对比原有 Hudi 表带来了的收益。
-
入湖的资源节省了 30%-40%。
-
写入性能提升了 3 倍。
-
部分查询的性能提升了 7 倍左右。
刚刚分享了 Paimon CDC 数据的入湖在吞吐方面的一些能力,下面介绍一下 Paimon 在 CDC 入湖上,给用户带来的一些比较方便的入湖工具。
比如在 Paimon 0.4 中,我们提供了 Flink CDC 的入湖。原生集成的 Flink CDC 提供 DataStream 作业,通过 Flink CDC 把 Changelog 的数据通过 Schema Evolution 的方式写入 Paimon。
表同步,它可以自动的管理表结构变更,增加列、删除列、变更类型、重命名列等等。也可以通过在表同步的定义,新增计算列、定义分区列、定义主键,以及做分库分表的同步。
此外,Paimon CDC 入湖还提供了整库同步,可以让整个库的表全部同步到 Paimon 中,你不用担心 OOM 或者容易挂掉。一个作业同步过来,可以尽可能减少同步的资源。还支持 INCLUDING、EXCLUDING,还支持表名前后缀,自动跳过失败表,动态新增表。
在 Paimon 0.5 中,我们提供了 Kafka 的同步。不仅可以通过 Flink CDC 同步进来,Kafka 里面的 CDC 数据也可以同步进来。你可以把你的数据库,TIDB、MySQL、Oracle 写到 Kafka 中,然后以 Schema Evolution 的同步,同步到 Paimon 中。
可以看到同步入湖非常简单,使用 Paimon 的 Flink action 就可以启动整个同步的作业。甚至 Paimon 还提供 CDC 的 DataStream 的 API,你可以直接调我们已经集成好的作业来同步数据,也可以通过 CDC 的 DataStream 的 API 编写自己的 Flink 流的 Schema Evolution 的 Pipeline。
Paimon 支持定义 Partial-update,你可以定义 Partial-update Engine。这样就可以通过不同的留写入不同的字段,后面可以批读,甚至 Paimon 也提供了流读,只要声明 Changelog Producer 就可以流读合并后的数据,它的查询也支持列裁剪的高效查询。
此外,Partial-update 的输入可能是乱序的,所以在 Partial-update 表,也可以定义 Sequence Field 处理乱序的情况。在 Paimon 0.5 中引入了 Sequence Group 的概念,为了解决每个流不同的乱序。如果它们共用一个版本字段,某个流更新之后有可能会导致另外一个流的最新版本不能更新。
举个例子,上游有两个表要更新,所以要定义两个 Sequence Group,这个 Sequence Group 的字段可以是不同的版本字段。这样不同的流只要更新自己的版本就可以了,不管两边多不对齐,它最终的数据都能被正确的更新上。
在 Paimon 中,它的流读是它的核心之一,这也是它区别其他数据湖的一个关键点所在。Paimon 可以流读原始数据,你可以设置 Changelog-producer=input。如果你的数据是一个完整的 CDC,就可以运用这种模式,它是最高效,也是消耗资源最少的。
如果你的流不是一个完整的 CDC,比如 Partial-update 这种输入。所以就要求下游的流读要生成一个变更日志,在 Paimon 这里不仅支持生成变更日志,还有两种非常灵活的模式,Lookup 模式和 Full-Compaction 模式。
Lookup 模式可以在写入的时候就动态 Lookup 高层的文件,查到最新的数据,合并最新的 Changelog 输出到下游。这是最快的,也是我们推荐 1-3 分钟时延的,但它的成本会高一些。
如果一些作业成本要求很低,且能接受更大延时,你可以用 Full-Compaction 模式。它在异步的 Full-Compaction 的时候,才会产生对应的 Changelog,可以把 Full-Compaction 的周期调度时间设置的更大,比如 10 分钟。它的好处是代价更低,但时延更高。
刚刚我们提到湖存储和流读有一个矛盾,它就是 FileNotFound。因为流存储要不断清理 snapshot,这样它的小文件才会少。但流读如果依赖一个很早 snapshot,一旦这个流作业挂了,它读的那个 snapshot 就会被清理,它就完全不能恢复了。
针对于问题,Paimon 提出了 Consumer-ID,它有点类似于 Kafka 的 Group-ID。它可以保证作业挂了重启之后,它读的那个 snapshot 不会被清理。
Paimon 0.4 在生态中也有比较大的进步,如上图所示。
最开始在 Paimon 中只是支持 Flink,它作为 Flink Table Store 支持 Flink 完整的生态和用法。
在 Paimon 0.4 中支持的更多了。比如在 Spark 中支持了 Batch Read、Batch Write,还可以在 Spark 中 Create Table、Alter Table;在 Hive 中支持了 Batch Reader、Batch Write、Create Table 等等;在 Trino 中支持了 Create Table、Alter Table 等等功能。
我们有两个引擎是集成比较完善的,一个是 Flink,另外一个是 Spark。我们希望它所有的功能,批读、批写、创建表、修改 Meta 等命令,在 Flink 和 Spark 中都支持的比较好。其次,我们希望其他引擎都能支持读 Paimon,甚至更多的操作,比如 Create Table、Write Table 等等。
除了这些传统的处理引擎,StarRocks、Doris、Seatunnel 也集成了 Paimon,整体的代码基本已经 ready 了,处于即将发布的状态。阿里云上的 MaxCompute、Hologres,网易的 Arctic,也已经在研发的路上了。
三、社会应用实践
目前开源社区主要的使用和参与者包括,阿里云、字节跳动、同程旅行、B 站、中原银行、米哈游、汽车之家等等企业。
接下来一起看一下,大家都是怎么用 Paimon 的。
在阿里云计算平台,Paimon 是数据湖的一号位,希望阿里云计算平台的所有计算全部集成到 Paimon 中,集成 Paimon、读 Paimon。最好的集成是实时计算 Flink 版平台,它是 Flink 以及开源大数据平台 E-MapReduce 里面,希望替代 Hudi 成为实时入湖的首选。
上图是 Apache Paimon,可以看到我们通过阿里云的 Flink 实时计算能入湖,能 CTAS 入湖,能通过阿里云实时计算 Flink 流读。也希望 Paimon 的数据能被 MaxCompute、Hologres 查询,也能在开源大数据平台 E-MapReduce 中融入的更好。
在字节跳动,工程师们使用 Paimon+Flink 作为血缘管理以及一致性查询的 Streaming Warehouse 生产体系。如上图所示,业务数据通过 Streaming ETL,类似于 Streaming materialize view 类似的概念,落到了 Streaming Warehouse 中。这样所有的 Paimon 表都能通过一致性的 Query 查询。
在同程旅行,引入 Paimon 主要优化了原有 Hudi 的近实时数仓。
-
在实时写入 ODS 层场景,Paimon 大概有 114+ 的作业;最大 Upsert 日增量 2000 万+;最大的表总量 90 亿+。
-
在局部更新场景,Paimon 有 10+的作业;应用了真·局部更新 (Sequence-Group) 的概念。
-
在流读\增量读场景,Paimon 有 20+ 流式增量读的作业;10+ 批处理小时级增量读的作业。
中原银行在探索流式数仓;米哈游也在探索流批一体技术;Bilibili 在攻坚 AI 方向,考虑 Partial-Update 的场景;尘锋信息在探索 TB 级数据入湖,建设了 Flink 流批一体 + Paimon 的流批一体数仓等等。
四、后续规划
我们希望能达到这样一个 Streaming LakeHouse。数据通过非常方便的入湖能入到 Paimon 中,也能通过 Paimon 的流读和批读建立 Streaming 的 Pipeline。同时,Paimon 也应该有一个非常好的生态,能被各种引擎查询。这就是 Paimon+Flink 往后走的一个大方向。
打造一个易用的、简单的 Streaming LakeHouse,大致有以下三个方向。
第一个方向:
-
在 CDC 处理中会有更多的 CDC 入湖。比如刚刚提到的 Kafka 的入湖,应该是更简单、更自然、更自动的。
-
目前 Paimon 还需要定一个 Bucket 个数。太小的 Bucket 性能比较差,数据量大了之后,吞吐就下来了。而太大的 Bucket,小文件又很多。虽然一个 Bucket 里是一个 LSM,它已经有比较好的吞吐,但你还是要调优。所以在 Paimon 0.5 中会提供一个动态的 Bucket,希望达到的状态是全自动的。
-
Create tag,希望 Paimon 实时入湖之后,每天能打出一个 tag 给离线生产用。
第二个方向:Append-Only 处理增强。Paimon 之前的 Append-Only 需要定义 Bucket,这是一个非常难定义的概念。所以后面 Paimon 应该支持真正的离线表,应该是没有 Bucket,且离线表的写入应该也包含小文件合并,并这也符合 Paimon 全自动的概念。
第三个方向:除了 StarRocks 的生态的对接,我们希望将 Spark 打造成第二个像 Paimon 一样集成非常好的引擎,Spark 读和写的能力都应该很好,甚至通过 Spark+Paimon,就能组成一个完整的数据湖。
接下来回顾一下 Paimon 的发展历程。2021 年在 Flink 社区讨论;2022 年 5 月发布了 Flink Table Store 的第一个版本;2023 年 1 月发布了 0.3,它是 Paimon 的一个生产可用的版本;3 月进入了孵化器,改名 Apache Paimon。2023 年 6 月,发布了 Paimon 0.4。
未来我们希望 CDC 实时数据湖完全成熟,Append 离线表生产可用,生态全面对接,Spark 进入成熟状态。
Q&A
问:CDC 写 Paimon 表 如果 binlog 流量每秒 3000records+全量初始化如何优化下。 目前测试看checkpoint 经常失败?
答:关键还是看性能瓶颈在哪里,是否有内存问题,最后看下 Jstack。
问:能不能动态修改表结构呢?
答:能啊,Spark 或者 Flink 1.17 都可。
问:0.5 大概什么时候发布?
答:8 月份左右。
问:请问流读的延迟怎么样?
答:最小 checkpoint 延时,也就是 1 分钟。
问:如何方便的从 Hudi 迁移到 Paimon 上?
答:能,现在推出的 SparkGenericCatalog 也是为了 Hudi 和 Paimon 表共存。
问:可以展开讲讲 Changelog 的 Lookup 模式吗?
答:可以看看官网
Primary Key Table | Apache Paimon
问:Bucket 是很重要的参数吗,怎么调优?
答:对,根据数据量实际跑下看看,目前最新也支持了动态 Bucket。
问:存储一段时间后,Bucket 可手动调整么?调整后之前的数据回重分么?
答:详见官网 Rescale Bucket
Rescale Bucket | Apache Paimon
问:实时数据乱序的情况下,Paimon 的 Partial-update 怎样避免旧数据覆盖新数据呢,有没有类似 sequence 列的实现?
答:有,详见官网 sequence-field
Primary Key Table | Apache Paimon
问:压缩时,是不是对读写的性能影响很大?
答:对写有影响,是读写的一个 tradeoff。
请关注 Paimon
流式数据湖的发展需要你的支持:
-
关注微信公众号:Apache Paimon,了解行业实践与最新动态
-
进入 Paimon 交流钉钉群:搜索 10880001919,讨论技术并得到实时的支持
-
Github GitHub - apache/incubator-paimon: Apache Paimon(incubating) is a streaming data lake platform that supports high-speed data ingestion, change data tracking and efficient real-time analytics. 点赞支持
点击查看原文视频 & 演讲PPT