Flink 自定义维表

写这个博客主要是看了袋鼠云的flinkStreamSQL git地址:https://github.com/DTStack/flinkStreamSQL  自己还往上提交了kudu的sink和side 第一次commit到github上面还是很开心的。

这里重点说的是flinkStreamSQL是如何完成side的,主要其实是两种缓存方案LRU和ALL。这里忽略所有的sql解析 注册等等,单纯的从流的角度完成维表join。

ALL相对比较简单先介绍ALL: 
从KuduAllReqRow开始,这里是维表的加载以及如何join。先查看继承关系,只看需要关心的。先看AllReqRow,AllReqRow只需要关心open()方法。这里是同步缓存,缓存完毕后数据才继续往下走。

     @Override
    public void open(Configuration parameters) throws Exception {
        super.open(parameters);
        //初始化全量维表数据
        initCache();
        System.out.println("----- all cacheRef init end-----");

        //start reload cache thread
        SideTableInfo sideTableInfo = sideInfo.getSideTableInfo();
        //创建线程池 开启调度线程 每隔一段时间查询全量数据 覆盖原有数据
        es = Executors.newSingleThreadScheduledExecutor(new DTThreadFactory("cache-all-reload"));
        es.scheduleAtFixedRate(() -> reloadCache(), sideTableInfo.getCacheTimeout(), sideTableInfo.getCacheTimeout(), TimeUnit.MILLISECONDS);
    }

这里其实就是主要的思想了,开启一个调度线程不停的去查询数据然后缓存。这里缓存用的是
AtomicReference<Map<String, List<Map<String, Object>>>> cacheRef = new AtomicReference<>(); 
第一个string: join的条件 List:维表中本条数据的 字段名 字段值 

以此条sql为例
insert into  MyResult
    select m.id,m.title,m.amount,s.tablename1
	from MyTable m  left join sideTable s on m.id=s.id ;

从streamAPI角度就是 MyTable流来了根据m.id的值去Map中查找是否存在对应的List,如果存在则根据字段名取出对应的值拼接到MyTable流中。

LRU: 主要是在SideAsyncOperator类中 主要方法getSideJoinDataStream()
 

    public static DataStream getSideJoinDataStream(DataStream inputStream, String sideType, String sqlRootDir, RowTypeInfo rowTypeInfo,  JoinInfo joinInfo,
                                            List<FieldInfo> outFieldInfoList, SideTableInfo sideTableInfo) throws Exception {
        AsyncReqRow asyncDbReq = loadAsyncReq(sideType, sqlRootDir, rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo);
        //TODO How much should be set for the degree of parallelism? Timeout? capacity settings?
        return AsyncDataStream.orderedWait(inputStream, asyncDbReq, 10000, TimeUnit.MILLISECONDS, asyncCapacity)
                .setParallelism(sideTableInfo.getParallelism());
    }

依然只看需要关注的类:

可以看到这里是用的异步IO查询,这里的查询是根据on后的条件 ,还是上面的逻辑代码 传入m.id=3  此时就会到数据库中查询s.id=3的数据 缓存到Cache<String, CacheObj> cache中 String是存入的值 如 3,CacheObj= new CacheObj(type, content)  type为枚举字段MissVal(为查询到数据),SingleLine(查询的数据只会有一条(1对1)),MultiLine(查询的数据有多条(1对多)) 。content为Object,如果是MultiLine 则表明content中需要存入多个数据。
缓存时间:
 

 cache = CacheBuilder.newBuilder()
                .maximumSize(sideTableInfo.getCacheSize())
                .expireAfterWrite(sideTableInfo.getCacheTimeout(), TimeUnit.MILLISECONDS)
                .build();

在初始化Cache<String, CacheObj> cache时已经决定了缓存的大小和时间。
从streamAPI角度就是 MyTable流来了根据m.id的值去数据库中查询,如果存在放入SingleLine或MultiLine,不存在则放入MissVal。然后缓存起来,这里调用的是异步IO查询。当有重复的key到来时就直接从缓存中获取数据往下发送。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值