在接触关系型API之前,用户通常会采用DataStream、DataSet API来编写Flink程序,它们都提供了丰富的处理能力,以DataStream为例,它有如下这些优点:
- 富有表现力的流处理,包括但不限于:转换数据,更新状态,定义窗口、聚合,事件时间语义,有状态且保证正确性等;
- 高度自定义的窗口逻辑:分配器、触发器、逐出器以及允许延迟等;
- 提升与外部系统连接能力的异步I/O接口;
- ProcessFunction给予用户访问时间戳和定时器等低层级的操作能力;
但它同时也存在一些使用壁垒导致它并不适合所有用户:
- 写DataStream程序并非总是很容易:流处理技术发展很快,一些概念层出不穷,比如,时间、状态、窗口等;
- 需要特殊的知识与技巧:持续的流计算应用需要特殊的要求以及Java/Scala的编程经验;
用户希望更专注于他们的业务逻辑,于是Flink提供了更具表达能力的API——关系型API。关系型API有很多好处:
- 它是声明式的,用户只需告知它们想要的,系统决定如何计算,用户不必指定具体的实现细节;
- 查询可被高效地优化和执行,相比之下底层API中的UDF则难于优化且需要人工调优;
- 大众(尤其是数据分析领域的从业者)对SQL的了解和熟悉程度要远高于特定的编程语言;
关系型API其实是Table API和SQL API的统称:
- Table API:为Java&Scala SDK提供类似于LINQ(语言集成查询)模式的API(自0.9.0版本开始)
- SQL API:支持标准SQL(自1.1.0版本开始)
关系型API作为一个统一的API层,既能够做到在Batch模式的表上进行可终止地查询并生成有限的结果集,同时也能做到在Streaming模式的表上持续地运行并生产结果流,并且在两种模式的表上的查询具有相同的语法跟语义。这其中最重要的概念是Table,Table与DataSet、DataStream紧密结合,DataSet和DataStream都可以很容易地转换成Table,同样转换回来也很方便。下面的代码段展示了采用关系型API编写Flink程序的示例:
val tEnv = TableEnvironment.getTableEnvironment(env)
//配置数据源
val customerSource = CsvTableSource.builder()
.path("/path/to/customer_data.csv")
.field("name", Types.STRING).field("prefs", Types.STRING)
.build()
//将数据源注册为一个Table
tEnv.registerTableSource(”cust", customerSource)
//定义你的table程序(在一个Flink程序中Table API和SQL API可以混用)
val table = tEnv.scan("cust").select('name.lowerCase(), myParser('prefs))
val table = tEnv.sql("SELECT LOWER(name), myParser(prefs) FROM cust")
//转换为DataStraem
val ds: DataStream[Customer] = table.toDataStream[Customer]
关系型API架构在基础的DataStream、DataSet API之上,其整体层次关系如下图所示:
它们提供等价的特性集合,并且可以在同一个程序中混合使用,两者都与Flink的core API紧密集成。从上图来看,上层有两种API,而其下有两个基础(DataSet、DataStream)API作为后端。那这是否意味着实现时的四种组合的转换路径呢?其实,Flink并没有自己去实现转换、SQL的解析、执行计划的生成、优化等操作,它将一些“不擅长”的任务转交给了Apache Calcite。整体架构如下图:
Apache Calcite是一个SQL解析与查询优化框架(这个定义是从Flink关注的视角来看,Calcite官方的定义为动态的数据管理框架),目前已被许多项目选择用来解析并优化SQL查询,比如:Drill、Hive、Kylin等。
我们来对上面的架构图进行解读。从中上部我们看到,可以从DataSet、DataStream以及Table Source等多种渠道来创建Table,Table相关的一些信息比如schema、数据字段及类型等信息统一被注册并存放到Calcite Catalog中。这些信息将为Table & SQL API提供元数据。接着往下看,Table API跟SQL构建的查询将被翻译成共同的逻辑计划表示,逻辑计划将作为Calcite优化器的输入。优化器结合逻辑计划以及特定的后端(DataSet、DataStream)规则进行翻译和优化,随之产生不同的计划。计划将通过代码生成器,生成特定的后端程序。后端程序的执行将返回DataSet或DataStream。
这个架构图展示了Flink关系型API的整体架构,也是后续我们分析这个模块的基础。
原文发布时间为:2017-07-06
本文作者:vinoYang
本文来自云栖社区合作伙伴CSDN博客,了解相关信息可以关注CSDN博客。