(转自我的微信公众号 KAMI说 )
在系列文前篇《FlinkSQL细粒度TTL配置的实现(一)》中,我们介绍了实现Flink SQL 细粒度TTL配置的基本原理:通过将原来一段SQL按照TTL的不同拆分为多段子SQL,然后逐个“翻译-重注册”,最终获得等价于原来一段SQL所描述的但各部分的TTL配置不一样的DataStream 作业
同时我们也发现,如果中间计算过程包含聚合计算等操作,对应输出的中间结果为带撤回标志位的数据流(简称撤回流)DataStream<Tuple<Boolean, Row>>
。Flink 目前无法将撤回流直接注册为动态表。
实现所有场景下的 Flink SQL 的细粒度 TTL 配置,关键在于解决撤回流注册为动态表的问题。
通过阅读Flink Table API & SQL 的包flink-table
的源码,我们知道:
- Flink Table API & SQL 使用 CRow 作为其内部数据流的基本数据类型,实际上是 Row 类型加上一个标志位
- 每个计算节点的语法逻辑树节点 RelNode 包含该节点的输出是否撤回流的属性
produceUpdates
,下游节点会根据这个属性,构造对应的计算逻辑 - 数据源注册到表环境后,对应的 DataStream RelNode 节点为 DataStreamScan 节点,属性
produceUpdates
没有显式实现,为其父类默认值:false,即非撤回流。
通过实现一个简单的MapFunction,我们可以直接把撤回流转为 CRow 数据流,即 DataStream<CRow>
。
同时,如果对源码进行一点修改,使得 CRow 数据流时,对应的 DataStreamScan 的属性 produceUpdates
设置为 true,那么就可以实现将撤回流注册为动态表这个关键特性。具体方法是:
-
CRow对应的TypeInfomation为 CRowTypeInfo。表环境的数据流注册方法的类型检查以及字段名称和下标构造的逻辑中,需要添加对CRowTypeInfo 的支持。当输入 DataStream类型为 CRowTypeInfo 时,从 CRowTypeInfo 构造 RowTypeInfo,以通过类型检查以及字段名称和下标构造:
// 文件 src/main/scala/org/apache/flink/table/api/TableEnvironment.scala /** 抱歉,因为这部分代码已经用于生产环境,为避免被公司安全扫描认为是源码泄漏事故,先临时移除。 这部分代码并不复杂,各位应该可以根据描述实现出来~ **/
-
RelNode 节点DataStreamScan 已经对就支持 CRow 做了支持,只需要实现属性
produceUpdates
。当输入 DataStream 类型为 CRowTypeInfo 时,返回True:// 文件 src/main/scala/org/apache/flink/table/plan/nodes/datastream/DataStreamScan.scala /** 抱歉,因为这部分代码已经用于生产环境,为避免被公司安全扫描认为是源码泄漏事故,先临时移除。 这部分代码并不复杂,各位应该可以根据描述实现出来~ **/
修改完成后,重新编译源码,运行下测试,通过了就OK啦。
带聚合操作的SQL的“翻译-重注册”的过程为:
-
通过表环境(即 StreamTableEnvironment)的方法
sqlQuery
,将SQL构建为对应的 Table 对象 -
使用表环境的翻译方法
toRetractStream
,将Table对象翻译为 DataStream 作业,通过MapFunction将其输出的撤回流转换为 CRow 流 -
通过Table 对象的 Schema,构造 CRow 流的数据类型声明
CRowTypeInfo
-
通过表环境的流注册方法
registerDataStream
将CRow流重新注册为动态表。
至此,所有场景下的Flink SQL 细粒度TTL配置的实现完成,希望对大家有帮助~
Tips: 如何判断Table对象的输出是撤回流还是非撤回流(即追加流,Append-Only Stream)?我们可以参考源码做法:
/**
* @param tEnv 流表环境
* @param query 查询语句对象
* @return 该查询是否 Append-Only
*/
static public boolean isAppendOnly(StreamTableEnvironment tEnv, Table query) {
return UpdatingPlanChecker.isAppendOnly(tEnv.optimize(query.getRelNode(), false));
}
PS. 修改源码不可避免有一定门槛,并且会带部署上的麻烦,我会尝试发起Pull Request,将撤回流注册为动态表的特性合并到 Flink 以后的版本中。
随手一赞,支持原创~
