Flink-异步IO关联Hbase维表

Flink在处理与外部系统交互时,通过默认的同步方式可能导致大量时间浪费在等待响应上。为提高效率,引入了异步IO(AsyncI/O),该特性在Flink 1.2版本中由阿里巴巴贡献,允许连续发送多个请求而不阻塞,减少了网络延迟的影响。异步查询通过线程池执行,避免单个查询造成的阻塞,提升了并发处理能力。代码示例展示了如何使用AsyncDataStream进行异步维度表查询并更新数据。

1.异步IO

在Flink 流处理过程中,经常需要和外部系统进行交互,如通过维度表补全事实表中的维度字段。
默认情况下,在Flink 算子中,单个并行子任务只能以同步方式与外部系统交互:将请求发送到外部存储,IO阻塞,等待请求返回,然后继续发送下一个请求。这种方式将大量时间耗费在了等待结果上。
为了提高处理效率,可以有两种思路。
(1)增加算子的并行度,但需要耗费更多的资源。
(2)异步 IO。

Flink 在1.2中引入了Async I/O,将IO操作异步化。在异步模式下,单个并行子任务可以连续发送多个请求,按照返回的先后顺序对请求进行处理,发送请求后不需要阻塞式等待,省去了大量的等待时间,大幅提高了流处理效率。
Async I/O 是阿里巴巴贡献给社区的特性,呼声很高,可用于解决与外部系统交互时网络延迟成为系统瓶颈的问题。
异步查询实际上是把维表的查询操作托管给单独的线程池完成,这样不会因为某一个查询造成阻塞,因此单个并行子任务可以连续发送多个请求,从而提高并发效率。对于涉及网络IO的操作,可以显著减少因为请求等待带来的性能损耗。

以下为flink异步IO代码片段

 //4.1 关联SKU
        SingleOutputStreamOperator<TradeTrademarkCategoryUserSpuOrderBean> withSkuDS = AsyncDataStream.unorderedWait(
                skuUserOrderDS,
                new DimAsyncFunction<TradeTrademarkCategoryUserSpuOrderBean>("DIM_SKU_INFO") {
                    @Override
                    public String getKey(TradeTrademarkCategoryUserSpuOrderBean input) {
                        return input.getSkuId();
                    }

                    @Override
                    public void join(TradeTrademarkCategoryUserSpuOrderBean input, JSONObject dimInfo) {
                        if (dimInfo != null) {
                            System.out.println("CATEGORY3_ID:" + dimInfo.getString("CATEGORY3_ID"));
                            input.setSpuId(dimInfo.getString("SPU_ID"));
                            input.setTrademarkId(dimInfo.getString("TM_ID"));
                            input.setCategory3Id(dimInfo.getString("CATEGORY3_ID"));
                        }
                    }
                },
                60, TimeUnit.SECONDS);

        //4.2 关联SPU
        SingleOutputStreamOperator<TradeTrademarkCategoryUserSpuOrderBean> withSpuDS = AsyncDataStream.unorderedWait(
                withSkuDS,
                new DimAsyncFunction<TradeTrademarkCategoryUserSpuOrderBean>("DIM_SPU_INFO") {
                    @Override
                    public String getKey(TradeTrademarkCategoryUserSpuOrderBean input) {
                        return input.getSpuId();
                    }

                    @Override
                    public void join(TradeTrademarkCategoryUserSpuOrderBean input, JSONObject dimInfo) {
                        if (dimInfo != null) {
                            input.setSpuName(dimInfo.getString("SPU_NAME"));
                        }
                    }
                },
                60, TimeUnit.SECONDS);

模板类 DimAsyncFunction,在其中定义了维度关联的具体流程

  • 根据流中对象获取维度主键。
  • 根据维度主键获取维度对象。
  • 用上一步的查询结果补全流中对象的维度信息。
public abstract class DimAsyncFunction<T> extends RichAsyncFunction<T, T> implements DimJoinFunction<T> {

    private Connection connection;
    private ThreadPoolExecutor threadPoolExecutor;

    private String tableName;

    public DimAsyncFunction(String tableName) {
        this.tableName = tableName;
    }

    @Override
    public void open(Configuration parameters) throws Exception {
        connection = DriverManager.getConnection(GmallConfig.PHOENIX_SERVER);
        threadPoolExecutor = ThreadPoolUtil.getThreadPoolExecutor();
    }

    @Override
    public void asyncInvoke(T input, ResultFuture<T> resultFuture) throws Exception {

        threadPoolExecutor.execute(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                //1.查询维表数据
                JSONObject dimInfo = DimUtil.getDimInfo(connection, tableName, getKey(input));

                //2.将维表数据补充到JavaBean中
                if (dimInfo != null) {
                    join(input, dimInfo);
                }

                //3.将补充之后的数据输出
                resultFuture.complete(Collections.singletonList(input));
            }
        });
    }

    @Override
    public void timeout(T input, ResultFuture<T> resultFuture) throws Exception {
        //再次查询补充信息
        System.out.println("TimeOut:" + input);
    }
}

Flink关联Hbase可以通过自己护索引的方式来实现。由于FlinkSQL的Hbase connector不会处理索引,我们可以在Hbase中创建一个索引,将需要关联的字段作为索引,并将索引与原始进行关联。这样,在查询时可以通过索引快速定位到需要的数据,而不需要进行全扫描。\[1\] 另外,在开发Flink时,我们可以将固定的度信息存储在Hbase或者Redis等第三方库中,以便与流进行关联查询输出。可以通过本地搭建一个Hbase环境,并构建一个Hbase公共调用类和异步调用Hbase的公共代码来实现这一功能。\[2\] 在异步IO访问Hbase时,可以编写一个工具类,通过继承RichAsyncFunction抽象类来实现异步IO操作。该工具类可以根据传入的rowKey来查询Hbase某个的数据,并返回查询结果集。\[3\]这样,我们就可以在Flink中使用该工具类来实现与Hbase关联操作。 #### 引用[.reference_title] - *1* [FlinkSQL流式关联Hbase方案(走二级索引)](https://blog.youkuaiyun.com/qq_32068809/article/details/122862330)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Flink查询关联Hbase输出](https://blog.youkuaiyun.com/Aaron_ch/article/details/123113871)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值