摘要:本文整理自阿里巴巴开发工程师罗宇侠&方盛凯,在 Flink Forward Asia 2022 流批一体专场的分享。本篇内容主要分为五个部分:
- 构建流批一体引擎的挑战
- Hive SQL on Flink
- 流批一体引擎的收益
- Demo
- 未来展望
点击查看原文视频 & 演讲PPT
目前,流和批仍然是相对割裂的。虽然我们在应用层统一了,但从接入层开始,不同的引擎依旧有不同的接入层、API 层、执行层。我们认为,统一的流批一体引擎应该是从接入层开始使用 SQL Gateway 作为接入层。在 API 层使用 Flink SQL 作为编写作业的主要语言,在执行层替换成统一的 Runtime。
为了达成统一的流体引擎,我们认为有以下两个难点:
为此我们围绕以下两点在 Flink 1.16 上做了大量改进,保证了 Hive SQL on Flink 构建流批一体引擎是可行的。
接下来我来讲一下 Flink 社区具体做的一些工作来使得基于 Hive SQL on Flink 构建流批一体引擎成为可能。
在这一方面,Flink 社区经过多个版本的打磨,做了大量的工作使得基于 Hive SQL on Flink 构建流批一体引擎能够在生产中可用。
第一,集成 Hive MetaStore。众所周知,在大数据领域,Hive MetaStore 已经是事实的元数据管理标准了,所以 Flink 在很早的版本就已经开始集成 Hive MetaStore。主要分为以下三方面的支持:
第二,集成 Hive 的 UDF。主要支持以下两方面:
第三,Hive 表的读写。主要支持以下几方面:
用户的 Hive SQL 如何在 Flink 中顺滑地运行?上图是 Flink 兼容 Hive SQL 的架构,可以看到,它被分成了两个不同的分支,Flink SQL 和 Hive SQL。然后它们会由不同的 Parser 去做解析,Flink SQL 通过 Flink Parser 做解析,Hive SQL 通过 Hive Parser 做解析,Hive Parser 的行为和 Hive 的行为保持一致。
接下来它们都会生成 Flink 里的 Logical Plan,Logical Plan 进行优化,生成 Physical Plan,Physical Plan 再进行翻译,生成具体的 Job Graph,最后交由 Flink Runtime 执行。
基于这套架构,我们可以很方便地扩展 Flink 来提供对其他语法的支持。另外通过这套架构,我们理论上还能达到对 Hive 语法的百分之百兼容。
接下来讲一下我们最后达到了怎样的效果。
第一,支持生产上常用的 Hive 语法。即生产上的作业能够很好地迁移到我们的 Flink 中执行。主要支持以下语法:
那么我们到底对 Hive SQL 的兼容度能达到多少呢?答案是 94%了。这个数字又是怎么得出来的呢?
如上图所示,之前的内容讲的是 API 层、执行层已经统一了。 那么我们如何在接入层也把它统一掉呢?就引出我们接下来要分享的 Flink SQL Gateway 了。
我们为什么引入 Flink SQL Gateway 呢?原因有以下三个:
基于以上的考量,Flink 社区引入了 Flink SQL Gateway。它有以下特点:
上图是 Flink SQL Gateway 的架构图,可以分成前端和后端。
后端提供了多租户能力,可以对接不同的集群,包括 Flink Standalone,Flink On Yarn 等。另外,它支持用户自定义的 Catalog,可以用默认的 Catalog,也可以用 MySQL Catalog、Hive Catalog。
SQL Gateway 目前提供了两个 Endpoint,分别是 REST Endpoint 和 HiveServer2 Endpoint。
从上图左侧可以看到目前一些 Hive 的生态工具,包括 Beeline、DBeaver、DolphinScheduler、Superset、Apache Zeppelin 等,都能很好的对接到 Flink SQL Gateway 上。
上面提到 HiveServer2 Endpoint 在兼容 Hive 生态的重要性,接下来让我们一起来看一下它的具体架构。从上图可以看到主要分为两层,Client 端和 Server 端。HiveServer2 实际上是定义了 Client 端和 Server 端的一套通信协议,如果要兼容 HiveServer2,我们只要实现 HiveServer2 定义的这套协议即可。通过兼容 HiveServer2 协议,我们可以在不修改 Client 的情况下,将请求调用都转发到 Flink SQL Gateway,并在 Flink 集群执行。
上图呈现的是 HiveServer2 和 HiveServer2 Endpoint 的对应关系。
HiveServer2 提供了直连 MetaStore 的能力,可以使用 Hive SQL,底层是批处理引擎,包括 MapReduce 或者 Spark 等。
HiveServer2 Endpoint 内置了 Hive Catalog,其实就是 Hive MetaStore。同时它也使用 Hive 语法,底层也是批处理引擎,即 Flink Batch 引擎。
讲了这么多关于 Hive 兼容的内容,最后我们能达到什么样的效果呢?
上面的图我们从上往下看。通常,用户的 SQL 脚本通过 Apache Zeppelin、Beeline 等客户端提交作业,然后通过 Hive 的 JDBC 提交到 HiveServer2 中,再交由底下具体的引擎来执行。
基于上述介绍的 Flink 对兼容 Hive 所做的工作,我们只需要将引擎层改成 Flink 将可以作业直接迁移到 Flink 上,从而达到了一个非常平滑且无缝迁移的过程。
基于 Hive SQL on Flink 构建了流批一体引擎,我们获得了以下收益:
联邦查询是指,查不同数据源的数据,再写到不同的数据存储中。Hive 本身虽然通过 storage handler 提供了查询不同数据源的数据,比如 MySQL、Hbase 等,但相对来说还是比较复杂和不太完善。所以 Flink 就对 Hive 语法进行了扩展,使其它可以很方便的进行联邦查询。
首先我们看一下上图中间这条非常典型的 Hive SQL,它将几个表 join 一下,distribute by 再写到下游。注意看一下红色字,就是需要我们额外改造的内容,改造的成本非常低,只要在 Table 前面加上 Catalog 的那么就能读到不同 Catalog 的数据。比如说我们注册一个 PG Catalog,直接把 PG Catalog 的名字加到这个表的前面,我们就能读到 PG Catalog 的数据。
基于这样一层改造和扩展,我们就能使用 Hive 语法查到不同数据源的数据,再写到不同的数据存储。
在传统的 Lambda 架构中,我们往往会有两条不同的 pipeline:
当批作业回刷结束后,用户可以通过应用层分析最终表的结果,进行实时大屏地展示,做相关的数据应用以及分析数据之中潜在的趋势。
今天,我们则聚焦在数据回刷这一层,演示如何通过 Hive on Flink 构建流批一体引擎。
我们在 Kafka 中提前灌注了一些实时订单表,在 HDFS 中灌注了之前已经有的一些历史订单表。
实时链路中,我们通过 Window 语义,按天级别将统计信息直接灌入 HDFS 中,实时地获取当前的销售量。而离线链路中,我们则通过 agg 语法可以在第二天凌晨汇总当天的订单信息。通过数据回刷,我们就可以得到统一的每日销售额统计。
下面用 Zeppelin 演示 Hive SQL on Flink 构建流批一体数仓的 Demo。
demo 演示:Hive SQL on Flink 构建流批一体引擎 - demo_哔哩哔哩_bilibili
以下是我们未来的一些规划:
在流批一体方面,虽然我们在这个版本已经做了极大的努力,但存储层仍然是不统一。比如在流上我们依旧使用 Kafka 作为中间结果的存放,在批上我们更倾向于使用 HDFS,因此存储层统一也是至关重要的。另外,Batch 的用户现在更倾向使用 Hive SQL 写作业,但我们更希望他们能将 Batch 作业全部迁移至 Flink Batch SQL 中来。所以,未来我们将不断提升 Batch SQL 的功能性。
在 Hive 的集成方面,主要分为以下 3 点:
在 Flink SQL Gateway 方面,它依旧处于起步的状态。我们将从以下三个方面来完善它:
点击查看原文视频 & 演讲PPT