维基百科的“Apache Flink”词条下,有这么一句描述: “Flink 并不提供自己的数据存储系统,但为 Amazon Kinesis、Apache Kafka、Alluxio、HDFS、Apache Cassandra 和 Elasticsearch 等系统提供了数据源和接收器”,很快,这句话的前半句或许将不再适用。
2021 年初,在 InfoQ 编辑部策划的全年技术趋势展望中,我们提到大数据领域将加速拥抱“融合”(或“一体化”)演进的新方向。本质是为了降低大数据分析的技术复杂度和成本,同时满足对性能和易用性的更高要求。如今,我们看到流行的流处理引擎 Apache Flink(下称 Flink)沿着这个趋势又迈出了新的一步。
1 月 8 日上午,Flink Forward Asia 2021 以线上会议的形式拉开帷幕。今年是 Flink Forward Asia(下文简称 FFA)落地中国的第四个年头,也是 Flink 成为 Apache 软件基金会顶级项目的第七年。伴随着实时化浪潮的发展和深化,Flink 已逐步演进为流处理的领军角色和事实标准。
回顾其演进历程,Flink 一方面持续优化其流计算核心能力,不断提高整个行业的流计算处理标准,另一方面沿着流批一体的思路逐步推进架构改造和应用场景落地。但在这些之外,Flink 长期发展还需要一个新的突破口。
在 Flink Forward Asia 2021 的主题演讲中,Apache Flink 中文社区发起人、阿里巴巴开源大数据平台负责人王峰(花名莫问)重点介绍了 Flink 在流批一体架构演进和落地方面的最新进展,并提出了 Flink 下一步的发展方向——流式数仓(Streaming Warehouse,简称 Streamhouse)。正如主题演讲标题“Flink Next, Beyond Stream Processing”所言,Flink 要从 Stream Processing 走向 Streaming Warehouse 去覆盖更大的场景,帮助开发者解决更多问题。而要实现流式数仓的目标,就意味着 Flink 社区要拓展适合流批一体的数据存储,这是 Flink 今年在技术方面的一个创新,社区相关工作已经在 10 月份启动,接下来这会作为 Flink 社区未来一年的一个重点方向来推进。
那么,如何理解流式数仓?它想解决现有数据架构的哪些问题?为什么 Flink 要选择这个方向?流式数仓的实现路径会是怎样的?带着这些问题,InfoQ 独家专访了莫问,进一步了解流式数仓背后的思考路径。
Flink 这几年一直在反复强调流批一体,即:使用同一套 API、同一套开发范式来实现大数据的流计算和批计算,进而保证处理过程与结果的一致性。莫问表示,流批一体更多是一种技术理念和能力,它本身不解决用户的任何问题,只有当它真正落到实际业务场景中,才能够体现出开发效率和运行效率上的价值。而流式数仓可以理解为流批一体大方向下对落地解决方案的思考。
流批一体的两个应用场景
在去年的 FFA 上,我们已经看到 Flink 流批一体在天猫双十一的落地应用,那是阿里首次在核心数据业务上真正规模化落地流批一体。如今一年过去了,Flink 流批一体在技术架构演进和落地应用两方面都有了新进展。
技术演进层面,Flink 流批一体 API 和架构改造已经完成,在原先的流批一体 SQL 基础上,进一步整合了 DataStream 和 DataSet 两套 API,实现了完整的 Java 语义层面的流批一体 API,架构上做到了一套代码可同时承接流存储与批存储。
在今年 10 月发布的 Flink 1.14 版本中,已经可以支持在同一个应用中混合使用有界流和无界流:Flink 现在支持对部分运行、部分结束的应用(部分算子已处理到有界输入数据流的末端)做 Checkpoint。此外,Flink 在处理到有界数据流末端时会触发最终 Checkpoint,以确保所有计算结果顺利提交到 Sink。
而批执行模式现在支持在同一应用中混合使用 DataStream API 和 SQL/Table API(此前仅支持单独使用 DataStream API 或 SQL/Table API)。
此外,Flink 更新了统一的 Source 和 Sink API,开始围绕统一的 API 整合连接器生态。新增的混合 Source 可在多个存储系统间过渡,实现诸如先从 Amazon S3 中读取旧的数据再无缝切换到 Apache Kafka 这样的操作。
在落地应用层面,也出现了两个比较重要的应用场景。
第一个是基于 Flink CDC 的全增量一体化数据集成。
数据集成、不同数据源之间的数据同步对于很多团队来说是刚需,但传统方案往往复杂度太高且时效性不好。传统的数据集成方案通常是离线数据集成和实时数据集成分别采用两套技术栈,其中涉及很多数据同步工具,比如 Sqoop、DataX 等,这些工具要么只能做全量要么只能做增量,开发者需要自己控制全增量的切换,配合起来比较复杂。
基于 Flink 的流批一体能力和 Flink CDC,只需要写一条 SQL,就可以做到先全量同步历史数据,再自动断点续传增量数据,实现一站式数据集成。全程无需用户判断和干预,Flink 能自动完成批流之间的切换并保证数据的一致性。
Flink CDC Connectors 作为一个独立的开源项目,从去年 7 月份开源以来,一直保持相当高速的发展,平均两个月一个版本。目前 Flink CDC 版本已经更新到 2.1 版本,并完成了很多主流数据库的适配,比如 MySQL、PostgreSQL、MongoDB、Oracle 等,更多数据库如 TiDB、DB2 等的对接工作也在进行中。可以看到已经有越来越多企业在自己的业务场景中使用 Flink CDC,InfoQ 前不久采访过的 XTransfer 就是其中之一。
第二个应用场景则是大数据领域最核心的数仓场景。
目前主流的实时离线一体化数仓架构通常如下图所示。
绝大部分场景都会使用 Flink+Kafka 来做实时数据流的处理,也就是实时数仓的部分,并将最终分析结果写入到一个在线服务层,用来展示或做进一步的分析。同时后台一定会有一个异步的离线数仓架构对实时数据作补充,每天定期运行大规模批量甚至是全量分析,或进行历史数据的定期修正等。
但这个经典架构存在一些显而易见的问题:首先,实时链路和离线链路使用的技术栈不同,必定会有两套 API,那么就需要两套开发流程,增加了开发成本;其次,实时离线技术栈不同,无法保证数据口径的一致性;再次,实时链路的中间队列数据不利于分析。如果用户想要分析实时链路中一个明细层的数据,其实非常不方便,很多用户目前采用的办法可能是先把这个明细层中的数据导出来,比如导到 Hive 做离线分析,但这个时效性会大幅下降,或者为了加速查询,把数据导入到其他 OLAP 引擎中,但这又会增加系统复杂度,且数据一致性同样很难保证。
Flink 流批一体的理念可以在上述场景下得到充分应用。在莫问看来,Flink 可以让当前业界主流数仓架构再进阶一层,实现真正端到端全链路的实时化分析能力,即:当数据在源头发生变化时就能捕捉到这一变化,并支持对它做逐层分析,让所有数据实时流动起来,并且对所有流动中的数据都可以实时查询。再借助 Flink 完备的流批一体能力,使用同一套 API 就可以同时支持灵活的离线分析。这样一来,实时、离线以及交互式查询分析、短查询分析等,就可以统一成一整套解决方案,成为理想中的“流式数仓(Streaming Warehouse)”。
理解流式数仓
流式数仓(Streaming Warehouse)更准确地说,其实是“make data warehouse streaming”,就是让整个数仓的数据全实时地流动起来,且是以纯流的方式而不是微批(mini-batch)的方式流动。目标是实现一个具备端到端实时性的纯流服务(Streaming Service),用一套 API 分析所有流动中的数据,当源头数据发生变化,比如捕捉到在线服务的 Log 或数据库的 Binlog 以后,就按照提前定义好的 Query 逻辑或数据处理逻辑,对数据进行分析,分析后的数据落到数仓的某一个分层,再从第一个分层向下一个分层流动,然后数仓所有分层会全部流动起来,最终流到一个在线系统里,用户可以看到整个数仓的全实时流动效果。在这个过程中,数据是主动的,而查询是被动的,分析由数据的变化来驱动。同时在垂直方向上,对每一个数据明细层,用户都可以执行 Query 进行主动查询,并且能实时获得查询结果。此外,它还能兼容离线分析场景,API 依然是同一套,实现真正的一体化。
目前业界还没有这样一个端到端全流式链路的成熟解决方案,虽然有纯流的方案和纯交互式查询的方案,但需要用户自己把两套方案加起来,必然会增加系统的复杂性,如果要再把离线数仓方案也加进来,系统复杂性问题就更大了。流式数仓要做的是在实现高时效性的同时,不进一步提高系统复杂性,让整个架构对于开发和运维人员来说都是非常简洁的。
当然,流式数仓是终态,要达成这个目标,Flink 需要一个配套的流批一体存储支持。其实 Flink 本身有内置的分布式 RocksDB 作为 State 存储,但这个存储只能解决任务内部流数据状态的存储问题。流式数仓需要一个计算任务之间的表存储服务:第一个任务将数据写进去,第二个任务就能从它实时地再读出来,第三个任务还能对它执行用户的 Query 分析。因此 Flink 需要再扩展出一个跟自身理念配套的存储,从 State 存储走出来,继续向外走。为此,Flink 社区提出了新的 Dynamic Table Storage,即具备流表二象性的存储方案。
流批一体存储:Flink Dynamic Table
Flink Dynamic Table(社区讨论详见 FLIP-188)可以理解为一套流批一体的存储,并无缝对接 Flink SQL。原来 Flink 只能读写像 Kafka、HBase 这样的外部表,现在用同一套 Flink SQL 语法就可以像原来创建源表和目标表一样,创建一个 Dynamic Table。流式数仓的分层数据可以全部放到 Flink Dynamic Table 中,通过 Flink SQL 就能实时地串联起整个数仓的分层,既可以对 Dynamic Table 中不同明细层的数据做实时查询和分析,也可以对不同分层做批量 ETL 处理。
从数据结构上看,Dynamic Table 内部有两个核心存储组件,分别是 File Store 和 Log Store。顾名思义,Flie Store 存储 Table 的文件存储形式,采用经典的 LSM 架构,支持流式的更新、删除、增加等;同时,采用开放的列存结构,支持压缩等优化;它对应 Flink SQL 的批模式,支持全量批式读取。而 Log Store 存储的是 Table 的操作记录,是一个不可变更序列,对应 Flink SQL 的流模式,可以通过 Flink SQL 订阅 Dynamic Table 的增量变化做实时分析,目前支持插件化实现。
对 Flie Store 的写入被封装在内置的 Sink 中,屏蔽了写入的复杂性。同时 Flink 的 Checkpoint 机制和 Exactly Once 机制能够保证数据的一致性。
目前 Dynamic Table 第一个阶段的实现方案已经完成,社区也在围绕这个方向展开更多讨论。根据社区的规划,未来的终态会实现 Dynamic Table 的服务化,真正形成一套 Dynamic Table 的 Service,实现完全实时化的流批一体存储。同时,Flink 社区也正在讨论将 Dynamic Table 作为 Flink 独立子项目运营和发布,不排除后续将其完全独立成为流批一体通用存储项目发展。最终,利用 Flink CDC、Flink SQL、Flink Dynamic Table 就可以构建一套完整的流式数仓,实现实时离线一体化的体验。整个流程及效果参见以下 demo 视频展示。
虽然整个流程初步走通,但真正要实现全实时链路且足够稳定,社区还需要逐步提升实现方案的质量,这其中包括 Flink SQL 在 OLAP 交互式场景下的优化、动态表存储性能和一致性的优化以及构建动态表服务化能力等诸多工作。流式数仓这个方向只是刚刚启动,并有了初步尝试,在莫问看来,设计没有问题,但后续还需要解决一系列工程问题。这就像设计一个先进制程芯片或 ARM 架构,很多人都能设计出来,但在要保证良品率的前提下把芯片生产出来,其实是很难的。流式数仓会是接下来 Flink 在大数据分析场景下最重要的一个方向,社区也会在这个方向上大力投入。
Flink 不止于计算
在大数据实时化转型大趋势之下,Flink 不只能做一件事情,它还能做更多。
业界原先对于 Flink 的定位更多是一个流处理器或流计算引擎,实际并非如此。莫问表示,Flink 原生也不只是计算,大家可能狭义上认为 Flink 是计算,但广义来说,Flink 本来就有存储。“Flink 能够靠流计算冲出重围,靠的就是有状态的存储,这是相对 Storm 来说更大的优势。”
现在 Flink 希望更进一步,实现一个覆盖更大范围实时化问题的解决方案,原有的存储就不够用了。而外部的存储系统或其他引擎体系跟 Flink 的目标和特性又不完全一致,无法跟 Flink 做很好的集成。比如 Flink 跟数据湖包括 Hudi、Iceberg 都做了集成,支持实时入湖、入湖实时增量分析,但这些场景仍然无法完全发挥出 Flink 全实时的优势,因为数据湖存储格式本质还是 Mini-Batch,Flink 在其中也会退化到 Mini-Batch 模式。这不是 Flink 最希望看到或最适合 Flink 的架构,所以它自然就需要自己再拓展出一套与 Flink 流批一体理念相配套的存储系统。
在莫问看来,对于一套大数据计算分析引擎,如果没有一套与其理念配套的存储技术体系支撑,是无法提供一套极致体验的数据分析解决方案的。这就类似于,任何优秀的算法都需要有相应的数据结构与其配套,才能以最佳效率解决问题。
为什么说 Flink 做流式数仓更合适?这是由 Flink 的理念决定的,Flink 的核心理念是以 Streaming 优先来解决数据处理的问题,而要让整个数仓的数据实时流动起来,Streaming 是必不可少的。在数据都流动起来之后,集合数据的流表二象性,以及 Flink 的流批一体分析能力,就可以对流动中的任何一个环节的数据进行分析,不管是短查询的秒级分析,还是离线的 ETL 分析,Flink 都具备相应能力。莫问表示,Flink 流批一体原来受到最大的限制就是中间没有能配套的存储数据结构,会让场景不好落地,只要把存储和数据结构补上,很多流批一体的化学反应自然就会出现。
那 Flink 自建数据存储系统,是否会对大数据生态中现有的数据存储类项目带来一定的冲击呢?对此莫问解释道,Flink 社区推出新的流批一体存储技术,是为了更好地配合自身流批一体计算的需求,会保持存储和数据的开放协议、开放的 API 和 SDK,后续也有计划将此项目独立发展。此外,Flink 也依然会积极对接业界主流存储项目,保持对外生态的兼容和开放。
大数据生态不同组件之间的边界正变得越来越模糊,莫问认为,当下的趋势是从单一组件能力走向一体化解决方案。“大家其实都在顺着这个趋势走,比如你可以看到很多数据库项目,原来是 OLTP 后来加上了 OLAP,最后都叫 HTAP,实际上就是融合了行存和列存,既支持 Serving,又支持分析,都是为了给用户提供一套完整的数据分析体验。”莫问进一步补充表示:“目前很多系统都开始不断拓展边界,从实时走向离线,或从离线走向实时,相互渗透。否则,用户就需要自己手动去组合各种技术组件,还要面对各种复杂性,门槛越来越高。所以,一体化的融合趋势是非常明显的。到底谁组合谁其实没有对错,关键是能不能用一种很好的融合方式,给用户提供最好的体验。谁做到了,谁就能赢得最后的用户。社区要有生命力、持续发展,仅仅把自己最擅长的领域做到极致是不够的,还要不断基于用户需求和场景去创新和突破边界,大部分用户的需求不一定在单一能力从 95 分到 100 分的差距上。”
据莫问估计,大约还需要一年左右的时间可以形成一个相对成熟的流式数仓方案。对于已经采用 Flink 作为实时计算引擎的用户,天然就适合去尝试新的流式数仓方案,用户接口完全兼容 Flink SQL。据透露,在最新的 Flink 1.15 版本就会发出第一个 Preview 版本,正在使用 Flink 的用户都可以先试一试。莫问表示,基于 Flink 的流式数仓刚刚启动,技术方案还需要进一步迭代,距离成熟还需要一定时间打磨,希望能有更多企业和开发者带着自己的需求参与进来一起建设,这才是开源社区的价值。
结语
大数据开源生态组件众多、架构复杂度高的问题已经被诟病了很多年,如今业界似乎已经在一定程度上达成共识,即通过融合、一体化来推动数据架构往简化的方向演进,尽管不同企业有不同的说法和实现路径。
在莫问看来,开源生态百花齐放很正常,每个技术社区都有自己擅长的领域,但真正要解决业务场景问题的话,还是需要一套一站式的解决方案,才能为用户提供简单易用的体验。因此他也认同总体趋势会往整合和融合的方向走,但可能性并不唯一,未来有可能专门有一个系统来负责整合所有组件,也有可能每个系统都逐渐演变成一体化。哪一种可能性才是终局,或许只能等时间给我们答案了。