flink异步读写外部数据源

异步需要考虑的问题其实很多。所以一般情况下能同步解决的就用同步。

这次是有个数据源QPS太高了。20万以上,同步吞吐跟不上。或者同样的处理速率,同步比异步消耗资源多太多。所以就想到了异步方法。需要外部数据源也支持异步访问。刚好是支持的。

异步IO官方文档:异步 I/O | Apache Flink

核心操作:

复制代码
SingleOutputStreamOperator<ArrayList<UsageToPegasus>> appIdStreamCompute = AsyncDataStream
                .orderedWait(appIdStream,
                        new MapAsynProcessState(clusterName, StatePegasusName, stateTtl),
                        asynTimeout,
                        TimeUnit.MILLISECONDS,
                        asynStateCapacity)
                .uid("uid1")
                .name("name1")
                .returns(arrayListTypeInfo)
                .disableChaining()
                ;

异步方法内部:

复制代码
public class MapAsynProcessState extends RichAsyncFunction<AppIdState, ArrayList<UsageToPegasus>> {


    public void open(Configuration parameters) throws Exception {
        super.open(parameters);
        client = PegasusClientFactory.createClient(properties);
        table = client.openTable(StatePegasusName);
        RuntimeContext runtimeContext = getRuntimeContext();
        OperatorMetricGroup metricGroup = runtimeContext.getMetricGroup();

        // 注册监控指标
        successCounter = metricGroup.counter("xxx1"); //falcon监控用。xxx1为指标名称
        failureCounter = metricGroup.counter("xxx");
        timeoutCounter = metricGroup.counter("xxx");
    }


//核心方法
public void asyncInvoke(AppIdState appState, ResultFuture<ArrayList<UsageToPegasus>> resultFuture) throws Exception {

        table.asyncMultiGet(appState.getHashKey().getBytes(), null, 30000).addListener(
                (PegasusTableInterface.MultiGetListener) future -> {
                    String gaid = appState.getHashKey();
                    if (future.isSuccess()) {
                        PegasusTableInterface.MultiGetResult res = future.get();
                        ConcurrentHashMap<Long, long[]> one_hour_map = new ConcurrentHashMap<>();
                        ConcurrentHashMap<Long, long[]> six_hour_map = new ConcurrentHashMap<>();


                处理逻辑......

                        successCounter.inc();
//                            successRateMeter.markEvent();
//结果回收 (非常重要)                            resultFuture.complete(Collections.singleton(longMapToResult(id, one_hour_map, six_hour_map, useLatest, current15minTimestamp)));
                        } //asyncMultiGet监听到结果处理完成
                        else { //asyncMultiGet监听成功,但没结果
//每条路都要有结果回收 (非常重要)    
//有些异常可以返回空,但是也需要返回resultFuture.complete(Collections.emptyList());
                          resultFuture.complete(Collections.singleton(longMapToResult(id, one_hour_map, six_hour_map, useLatest, current15minTimestamp)));
                            System.out.println("本次查询成功,但是结果为空,这个用户当前尚没有记录");
                        }



}

}

注意结果回收:resultFuture.complete(Collections.singleton(结果对象))

//有些异常可以返回空,但是返回这个动作不能省。 resultFuture.complete(Collections.emptyList());

之前有出现过一个bug。异常情况没有回收,flink程序卡住运行不了。加上回收以后就好了。

写部分:

复制代码
写部分:

{
            Future<Void> setFuture = table.asyncSet(
                    appState.getHashKey().getBytes(),
                    appState.getSortKey().getBytes(),
                    MapSerializeAndDeserialize.serializeHashMap(appState.getAppState()),
                    stateTtl,
                    0);

            setFuture.addListener((PegasusTableInterface.SetListener) future ->{
                if (future.isSuccess()) {
                    stateSetSuccessCounter.inc();
                } else {
                    stateSetFailureCounter.inc();
                    System.err.println("写状态失败的原因是"+future.cause());
                }
            });

另外的示例:

复制代码
inal Future<Void> pegasusResultFuture = this.table.asyncSet(pegasusKey.getBytes(), realtimeSampleSortKey, streamSample.getFeatureRowBytes(), ttl, 10000);

        CompletableFuture.supplyAsync(  // 写Pegasus
                        () -> {
                            try {
                                markEventSync(metricGroup, counterMap, "pegasus_write", ENV);
                                return pegasusResultFuture.get();
                            } catch (Exception e) {
                                markEventSync(metricGroup, counterMap, "pegasus_write_err_1", ENV);
                                LOGGER.error("Pegasus write error: ", e);
                                return null;
                            }
                        })
                .handle(
                        (Void dbResult, Throwable throwable) -> {
                            // 异步查询异常,可进行重试
                            if (throwable != null) {
                                markEventSync(metricGroup, counterMap, "pegasus_write_err_2", ENV);
                                LOGGER.warn("Future complete error: ", throwable);
                                resultFuture.completeExceptionally(throwable);
                                return "fail";
                            }
                            markEventSync(metricGroup, counterMap, "pegasus_write_success", ENV);
                            resultFuture.complete(Collections.singleton(streamSample));
                            return "success";
                        });
    }
相关推荐
喵个咪11 小时前
GoWind Admin 拆解:BI 大屏设计器——schema 即 JSON、resolver 注入与三张快照表的口径谱系
大数据·后端·go
武子康12 小时前
H3-World 的 11.3 小时训练数据,是怎样对齐成动作监督的?
大数据·人工智能·深度学习
字节跳动数据平台13 小时前
火山引擎知识引擎VeKnow进化之路(下):让 AI 智能体更可用、更可信、更懂业务
大数据
Elastic 中国社区官方博客13 小时前
更少的位数,相同的召回率:DiskBBQ 更保守的自动校准扫描
大数据·运维·开发语言·人工智能·elasticsearch·搜索引擎
MyBili14 小时前
Chrome隐私安全配置:完整防护指南
大数据·chrome·谷歌浏览器·隐私安全·浏览器防护·cookie管理·上网痕迹清理
真上帝的左手14 小时前
19. 大数据-数据同步-工具
大数据·数据同步
数字孪生视频孪生14 小时前
在线重构,实时同步:视频动态三维重建打造 “常更常新” 的数字底座
大数据·人工智能·重构·架构·空间计算
Aloudata15 小时前
Claude 做数据分析的这两年:一份复盘与发展线索
大数据·数据库·人工智能·数据挖掘·数据分析·dataagent
云上工程笔记15 小时前
SRT字幕一键转手绘动画:srt-whiteboard-animation的复刻实录
大数据·开发语言·javascript·人工智能·机器学习
isNotNullX1 天前
仓储管理最全框架:6大流程、8项指标、10个管理动作、12个常见问题
大数据·人工智能