共计 5680 个字符,预计需要花费 15 分钟才能阅读完成。
Apache Flink 是大数据畛域十分风行的流批对立的计算引擎,数据湖是适应云时代倒退潮流的新型技术架构。那么当 Apache Flink 遇见数据湖时,会碰撞出什么样的火花呢?本次分享次要包含以下核心内容:
- 数据湖的相干背景介绍;
- 经典业务场景介绍;
- 为什么抉择 Apache Iceberg;
- 如何通过 Flink+Iceberg 实现流式入湖
- 社区将来布局工作。
视频回顾:https://www.bilibili.com/vide…
数据湖的相干背景介绍
数据湖是个什么概念呢?一般来说咱们把一家企业产生的数据都保护在一个平台内,这个平台咱们就称之为“数据湖”。
看上面这幅图,这个湖的数据起源多种多样,有的可能是结构化数据,有的可能是非构造数据,有的甚至是二进制数据。有一波人站在湖的入口,用设施在检测水质,这对应着数据湖上的流解决作业;有一批抽水机从湖外面抽水,这对应着数据湖的批处理作业;还有一批人在船头钓鱼或者在岸上捕鱼,这对应着数据科学家从数据湖中通过机器学习的伎俩来提取数据价值。
- 咱们总结起来,其实数据湖次要有 4 个方面的特点。
- 第一个特点是存储原始数据,这些原始数据起源十分丰盛;
- 第二个特点是反对多种计算模型;
- 第三个特点是有欠缺的数据管理能力,要能做到多种数据源接入,实现不同数据之间的连贯,反对 schema 治理和权限治理等;
- 第四个特点是灵便的底层存储,个别用 ds3、oss、hdfs 这种便宜的分布式文件系统,采纳特定的文件格式和缓存,满足对应场景的数据分析需要。
那么开源数据湖架构个别是啥样的呢?这里我画了一个架构图,次要分为四层:
- 最底下是分布式文件系统,云上用户 S3 和 oss 这种对象存储会用的更多一些,毕竟价格便宜很多;非云上用户个别采纳本人保护的 HDFS。
- 第二层是数据减速层。数据湖架构是一个存储计算彻底拆散的架构,如果所有的数据拜访都近程读取文件系统上的数据,那么性能和老本开销都很大。如果能把常常拜访到的一些热点数据缓存在计算节点本地,这就十分天然的实现了冷热拆散,一方面能播种到不错的本地读取性能,另一方面还节俭了近程拜访的带宽。这一层外面,咱们个别会抉择开源的 alluxio,或者抉择阿里云上的 Jindofs。
- 第三层就是 Table format 层,次要是把一批数据文件封装成一个有业务意义的 table,提供 ACID、snapshot、schema、partition 等表级别的语义。个别对应这开源的 Delta、Iceberg、Hudi 等我的项目。对一些用户来说,他们认为 Delta、Iceberg、Hudi 这些就是数据湖,其实这几个我的项目只是数据湖这个架构外面的一环,只是因为它们离用户最近,屏蔽了底层的很多细节,所以才会造成这样的了解。
- 最上层就是不同计算场景的计算引擎了。开源的个别有 Spark、Flink、Hive、Presto、Hive MR 等,这一批计算引擎是能够同时拜访同一张数据湖的表的。
经典业务场景介绍
那么,Flink 和数据湖联合能够有哪些经典的利用场景呢?这里咱们探讨业务场景时默认选型了 Apache Iceberg 来作为咱们的数据湖选型,前面一节会具体论述选型背地的理由。
首先,Flink+Iceberg 最经典的一个场景就是构建实时的 Data Pipeline。业务端产生的大量日志数据,被导入到 Kafka 这样的音讯队列。使用 Flink 流计算引擎执行 ETL 后,导入到 Apache Iceberg 原始表中。有一些业务场景须要间接跑剖析作业来剖析原始表的数据,而另外一些业务须要对数据做进一步的提纯。那么咱们能够再新起一个 Flink 作业从 Apache Iceberg 表中生产增量数据,通过解决之后写入到提纯之后的 Iceberg 表中。此时,可能还有业务须要对数据做进一步的聚合,那么咱们持续在 iceberg 表上启动增量 Flink 作业,将聚合之后的数据后果写入到聚合表中。
有人会想,这个场景如同通过 Flink+Hive 也能实现。Flink+Hive 确实能够实现,但写入到 Hive 的数据更多地是为了实现数仓的数据分析,而不是为了做增量拉取。一般来说,Hive 的增量写入以 partition 为单位,工夫是 15min 以上,Flink 长期高频率地写入会造成 partition 收缩。而 Iceberg 答应实现 1 分钟甚至 30 秒的增量写入,这样就能够大大提高了端到端数据的实时性,下层的剖析作业能够看到更新的数据,上游的增量作业能够读取到更新的数据。
第二个经典的场景,就是能够用 Flink+Iceberg 来剖析来自 MySQL 等关系型数据库的 binlog 等。一方面,Apache Flink 曾经原生地反对 CDC 数据解析,一条 binlog 数据通过 ververica flink-cdc-connector 拉取之后,主动转换成 Flink Runtime 能辨认的 INSERT、DELETE、UPDATE_BEFORE、UPDATE_AFTER 四种音讯,供用户做进一步的实时计算。
另外一方面,Apache Iceberg 曾经较为欠缺地实现了 equality delete 性能,也就是用户定义好待删除的 Record,间接写到 Apache Iceberg 表内就能够删除对应的行,自身就是为了实现数据湖的流式删除。在 Iceberg 将来的版本中,用户将不须要设计任何额定的业务字段,不必写几行代码就能够实现 binlog 流式入湖到 Apache Iceberg(社区的这个 Pull Request 曾经提供了一个 flink 写入 CDC 数据的原型)。
此外,CDC 数据胜利入湖 Iceberg 之后,咱们还会买通常见的计算引擎,例如 Presto、Spark、Hive 等,他们都能够实时地读取到 Iceberg 表中的最新数据。
第三个经典场景是近实时场景的流批对立。在罕用的 lambda 架构中,咱们有一条实时链路和一条离线链路。实时链路个别由 Flink、Kafka、HBase 这些组件构建而成,而离线链路个别会用到 Parquet、Spark 等组件构建。这外面波及到计算组件和存储组件都十分多,系统维护老本和业务开发成本都十分高。有很多场景,他们的实时性要求并没有那么刻薄,例如能够放松到分钟级别,这种场景咱们称之为近实时场景。那么,咱们是不是能够通过 Flink + Iceberg 来优化咱们罕用的 lambda 架构呢?
咱们能够用 Flink+Iceberg 把整个架构优化成上图所示。实时的数据通过 Flink 写入到 Iceberg 表中,近实时链路仍然能够通过 flink 计算增量数据,离线链路也能够通过 flink 批计算读取某个快照做全局剖析,失去对应的剖析后果,供不同场景下的用户读取和剖析。通过这种改良之后,咱们把计算引擎对立成了 Flink,把存储组件对立成了 Iceberg,整个零碎的保护开发成本大大降低。
第四个场景,是采纳 Iceberg 全量数据和 Kafka 的增量数据来 Bootstrap 新的 Flink 作业。咱们现有的流作业在线上跑着,忽然有一天某个业务方跑过来说,他们遇到一个新的计算场景,须要设计一个新的 Flink 作业,跑一遍去年一年的历史数据,跑完之后再对接到正在产生的 Kafka 增量数据。那么这时候应该怎么办呢?
咱们仍然能够采纳常见的 lambda 架构,离线链路通过 kafka->flink->iceberg 同步写入到数据湖,因为 Kafka 老本较高,保留最近 7 天数据即可,Iceberg 存储老本较低,能够存储全量的历史数据(依照 checkpoint 拆分成多个数据区间)。启动新 Flink 作业的时候,只须要去拉 Iceberg 的数据,跑完之后平滑地对接到 kafka 数据即可。
第五个场景和第四个场景有点相似。同样是在 lambda 架构下,实时链路因为事件失落或者达到程序的问题,可能导致流计算端后果不肯定齐全精确,这时候个别都须要全量的历史数据来勘误实时计算的后果。而咱们的 Iceberg 能够很好地充当这个角色,因为它能够高性价比地治理好历史数据。
为什么抉择 Apache Iceberg
回到上一节遗留的一个问题,为什么过后 Flink 在泛滥开源数据湖我的项目中会抉择 Apache Iceberg 呢?
咱们过后具体地调研了 Delta、Hudi、Iceberg 三个开源我的项目,并写了一篇调研报告。咱们发现 Delta 和 Hudi 跟 Spark 的代码门路绑定太深,尤其是写入门路。毕竟过后这两个我的项目设计之初,都多多少少把 Spark 作为的他们默认的计算引擎了。而 Apache Iceberg 的方向十分动摇,主旨就是要做一个通用化设计的 Table Format。因而,它完满地解耦了计算引擎和底下的存储系统,便于接入多样化计算引擎和文件格式,能够说正确地实现了数据湖架构中的 Table Format 这一层的实现。咱们认为它也更容易成为 Table Format 层的开源事实标准。
另外一方面,Apache Iceberg 正在朝着流批一体的数据湖存储层倒退,manifest 和 snapshot 的设计,无效地隔离不同 transaction 的变更,十分不便批处理和增量计算。而咱们晓得 Apache Flink 曾经是一个流批一体的计算引擎,能够说这二者的长远规划完满匹配,将来二者将合力打造流批一体的数据湖架构。
最初,咱们还发现 Apache Iceberg 这个我的项目背地的社区资源十分丰盛。在国外,Netflix、Apple、Linkedin、Adobe 等公司都有 PB 级别的生产数据运行在 Apache Iceberg 上;在国内,腾讯这样的巨头也有十分宏大的数据跑在 Apache Iceberg 之上,他们最大的一个业务每天有几十 T 的增量数据写入到 Apache Iceberg。社区成员同样十分资深和多样化,领有来自其余我的项目的 7 位 Apache PMC,1 为 VP。体现在代码和设计的 review 上,就变得十分刻薄,一个略微大一点的 PR 波及 100+ 的 comment 很常见。在我集体看来,这些都使得 Apache Iceberg 的设计 + 代码品质比拟高。
正式基于以上思考,Apache Flink 最终抉择了 Apache Iceberg 作为第一个数据湖接入我的项目。
如何通过 Flink+Iceberg 实现流式入湖
目前,咱们曾经在 Apache Iceberg 0.10.0 版本上实现 Flink 流批入湖性能,同时还反对 Flink 批作业查问 Iceberg 数据湖的数据。具体对于 Flink 如何读写 Apache Iceberg 表,能够参考 Apache Iceberg 社区的应用文档,这里不再赘述。
https://github.com/apache/ice…
上面来简要论述下 Flink iceberg sink 的设计原理:因为 Iceberg 采纳乐观锁的形式来实现 Transaction 的提交,也就是说两个人同时提交更改事务到 Iceberg 时,后开始的一方会一直重试,等先开始的一方顺利提交之后再从新读取 metadata 信息提交 transaction。思考到这一点,采纳多个并发算子去提交 transaction 是不适合的,容易造成大量事务抵触,导致重试。
所以,咱们把 Flink 写入流程拆成了两个算子,一个叫做 IcebergStreamWriter,次要用来写入记录到对应的 avro、parquet、orc 文件,生成一个对应的 Iceberg DataFile,并发送给上游算子;另外一个叫做 IcebergFilesCommitter,次要用来在 checkpoint 到来时把所有的 DataFile 文件收集起来,并提交 Transaction 到 Apache iceberg,实现本次 checkpoint 的数据写入。
了解了 Flink Sink 算子的设计后,下一个比拟重要的问题就是:如何正确地设计两个算子的 state?
首先,IcebergStreamWriter 的设计比较简单,次要工作是把记录转换成 DataFile,并没有简单的 State 须要设计。IcebergFilesCommitter 绝对简单一点,它为每个 checkpointId 保护了一个 DataFile 文件列表,即 map<Long, List<DataFile>>,这样即便两头有某个 checkpoint 的 transaction 提交失败了,它的 DataFile 文件依然保护在 State 中,仍然能够通过后续的 checkpoint 来提交数据到 Iceberg 表中。
社区将来布局工作等
Apache Iceberg 0.10.0 版本的公布,曾经拉开集成 Flink 和 Iceberg 的尾声。在将来的 Apache Iceberg 0.11.0 和 0.12.0 版本中,咱们布局了更多高级性能及个性。
对于 Apache 0.11.0 版本来说,次要解决两个问题:
第一个事件是小文件合并的问题,当然 Apache Iceberg 0.10.0 版本曾经反对了 Flink 批作业定时去合并小文件,这个性能还绝对较为高级。在 0.11.0 版本中,咱们将设计主动合并小文件性能,简略来说就是在 Flink checkpoint 达到,触发 Apache Iceberg transaction 提交后,有一个专门的算子,专门负责解决小文件的合并工作。
第二个事件是 Flink streaming reader 的开发,目前咱们曾经在公有仓库做了一些 PoC 工作,在将来的工夫内咱们将奉献到 Apache Iceberg 社区。
对于 0.12.0 版本来说,次要解决 row-level delete 的问题。如后面提到,咱们曾经在 PR 1663 中实现 Flink UPSERT 更新数据湖的全链路买通。后续在社区达成统一之后,将逐渐推动该性能到社区版本。到时候用户将能通过 Flink 实现 CDC 数据的实时写入和剖析,也能够不便地把 Flink 的聚合后果 upsert 到 Apache Iceberg 内。
作者介绍:
胡争(子毅),阿里巴巴技术专家,目前次要负责 Flink 数据湖计划的设计和开发工作,Apache Iceberg 及 Apache Flink 我的项目的长期沉闷贡献者,《HBase 原理与实际》作者。