现在最新版本的flink1.6版本现在还不支持直接用SQL来实现流与维表的join。这里打个广告我们团队已经实现了这个功能并且开源 https://github.com/DTStack/flinkStreamSQL

这里先解释下什么是维表;维表是动态表,表里所存储的数据有可能不变,也有可能定时更新,但是更新频率不是很频繁。在业务开发中一般的维表数据存储在关系型数据库如mysql,oracle等,也可能存储在hbase,redis等nosql数据库。

所以要用FlinkSQL实现流与维表的join 分两步;第一是用flink api实现维表的功能:
要实现维表功能就要用到 flink Aysnc I/O 这个功能,是由阿里巴巴贡献给apache flink的。具体介绍可以看这篇文章 http://wuchong.me/blog/2017/05/17/flink-internals-async-io/,这里不做介绍。
对应到flink 的api就是RichAsyncFunction 这个抽象类,继层这个抽象类实现里面的open(初始化),asyncInvoke(数据异步调用),close(停止的一些操作)方法,最主要的是实现asyncInvoke 里面的方法。流与维表的join会碰到两个问题,一个是性能问题,因为流速要是很快,每一条数据都需要到维表做下join,但是维表的数据是存在第三方存储系统,如果实时访问第三方存储系统,一个是join的性能会差,每次都要走网络io;还有就是对第三方存储系统带来很大的压力,有可能会把第三方存储系统搞挂掉。所以解决的方法就是维表里的数据要缓存,可以全量缓存,这个主要是维表数据不大的情况,还有一个是LRU缓存,维表数据量比较大的情况。第二个问题是流延迟过来的数据这么跟之前的维表数据做关联;这个就涉及到维表数据需要存储快照数据,所以这样的场景用hbase 做维表是比较适合的,因为hbase 是天生支持数据多版本的。

第二是解析流与维表join的sql语法转化成底层的flinkAPI
因为flinkSQL已经做了大部分sql场景,我们不可能在去解析sql的所有语法,在把他转化成底层flinkAPI。所以我们做的就是解析sql语法,来找到join表里有没有维表,如果有维表,那我们会把这个join的维表的语句单独拆来,用flink的tableAPI和streamAPi 生成新DataStream,在把这个DataStream与其他的表在做join这样就能用SQL来实现流与维表的join语法了。sql解析的工具就是用apache calcite,flink也是用这个框架做sql解析的。所以所有语法都是可以解析的。