Apache flink Ververica Flink培训教材中关于过期状态解的困惑

Apache flink Ververica Flink培训教材中关于过期状态解的困惑,apache-flink,connect,Apache Flink,Connect,不幸的是,ververica最初的培训被更改并重定向到另一个页面,这导致我无法再次查看该示例的介绍,我确实找到了一些其他示例,但对于这个特定的示例,我没有找到它,这是我最近一直在努力的事情 对于核心部件代码段,如下所示: 第一种处理乘车流的方法 @Override public void processElement1(TaxiRide ride, Context context, Collector<Tuple2<TaxiRide, TaxiFare

不幸的是,ververica最初的培训被更改并重定向到另一个页面,这导致我无法再次查看该示例的介绍,我确实找到了一些其他示例,但对于这个特定的示例,我没有找到它,这是我最近一直在努力的事情

对于核心部件代码段,如下所示: 第一种处理乘车流的方法

        @Override
        public void processElement1(TaxiRide ride, Context context, Collector<Tuple2<TaxiRide, TaxiFare>> out) throws Exception {
            TaxiFare fare = fareState.value();
            TimerService service = context.timerService();
            System.out.println("ride time service current watermark ===> " + service.currentWatermark() + "; timestamp ===>" + context.timestamp());
            System.out.println("ride state ===> " + fare);
            if (fare != null) {
                System.out.println("fare is not null ===>" + fare.rideId);
                fareState.clear();
                context.timerService().deleteEventTimeTimer(fare.getEventTime());
                out.collect(new Tuple2(ride, fare));
            } else {
                System.out.println("update ride state ===> " + ride.rideId + "===>" + context.timestamp());
                rideState.update(ride);
                System.out.println(rideState.value());
                // as soon as the watermark arrives, we can stop waiting for the corresponding fare
                context.timerService().registerEventTimeTimer(ride.getEventTime());
            }
        }
第二个是,因为ValueState是一个值,而不是一个包含很多值的列表,对于每次调用processElemnt2,如果ride为null,它将转到else,在调用fareState.update()之后,它将更改ValueState的值,从我的角度看,这意味着它认为ValueState的前一个值是匹配的,对吗-----最大的难题 谢谢你的回答,我非常感谢你的帮助

关于和的新教程将帮助您解答问题。但简单地说:

  • 您无法控制调用
    processElement1
    processElement2
    回调的顺序。这两个输入流相互竞争,Flink运行时将根据需要处理来自一个流或另一个流的事件。在计时和/或排序很重要的情况下,您可能会发现有必要在托管Flink状态下缓冲事件,直到您的应用程序准备好处理它们为止

  • ValueState是一种键控状态,这意味着无论何时访问或更新状态,都会读取或写入状态后端中上下文中键的条目。“上下文中的键”是正在处理的流元素的键(在
    processElement
    回调的情况下),或者是创建计时器的键(在
    onTimer
    回调的情况下)

  • 此外,请记住,在本练习中,每个钥匙最多有一个出租车和一个出租车票价

    本练习的参考解决方案说明了一种思考如何管理可能发生泄漏的状态的方法,但这种情况下没有一个明显正确的答案。本练习的目的是激发一些关于如何与状态和计时器一起工作的思考,并将涉及的一些问题浮出水面

    对于一个好的解决方案,我们的目标是什么?它应该

    • 产生正确的结果
    • 不泄漏状态
    • 易懂
    • 表现良好
    现在,让我们在考虑这些目标的情况下检查建议的解决方案。我们在
    processElement1
    中发现了该代码(顺便说一下,
    processElement2
    是相同的,只是在乘坐和票价之间角色颠倒):

    public void processElement1(滑行设施、上下文、收集器输出)引发异常{
    出租车票价=fareState.value();
    如果(票价!=null){
    fareState.clear();
    context.timerService().deleteEventTimeTimer(fare.getEventTime());
    外出。领取(新的Tuple2(乘车、车费));
    }否则{
    骑乘状态更新(骑乘);
    //一旦水印到达,我们就可以停止等待相应的车费
    context.timerService().RegisterEventTimer(ride.getEventTime());
    }
    }
    
    这意味着

    • 每当一个未完成配对的事件到达时,我们将其存储在状态并创建一个计时器
    • 每当一个完成配对的事件到达时,我们清除状态并删除匹配事件(先前存储的)的计时器
    所以很明显,如果这两个事件都发生了,就不会有任何泄漏。但是如果有一个不见了呢

    在这种情况下,计时器将在某个点启动,并运行此代码,这将清除可能存在的任何状态:

    public void onTimer(长时间戳、OnTimerContext ctx、收集器输出)引发异常{
    if(fareState.value()!=null){
    输出(不匹配的区域,fareState.value());
    fareState.clear();
    }
    if(rideState.value()!=null){
    ctx.output(unmatchDrides,rideState.value());
    清除();
    }
    }
    
    好的,但是我们怎么决定要等多久呢?等待ride.getEventTime()足够吗

    ride.getEventTime()
    设置事件时间计时器的效果是等待,直到解决了乘坐和票价流中的任何无序情况。当水印到达ride.getEventTime(),时,所有早期的乘车和票价事件都已到达,假设水印是完美的

    在这些练习中,水印实际上是完美的——不可能有延迟事件。但是在现实环境中,您应该预料到一些后期事件,并且我们应该预料我们的实现在这种情况下会正确运行。此参考解决方案将执行以下操作:

    • 匹配对中的一个事件将首先到达,并创建一个计时器来安排其最终删除
    • 计时器将启动,事件将被清除
    • 匹配事件延迟到达,并创建另一个计时器,在本例中是针对已经过去的时间
    • 下一个到达的水印触发该计时器,并且状态被清除
    换句话说,当事件延迟时,不会泄漏任何状态,但不会生成生成的联接。因此,如果您希望在延迟到达数据的情况下仍能产生结果,则应创建计时器,通过将必要状态保留一段时间来适应延迟,例如

    context.timerService().RegisterEventTimer(ride.getEventTime()+允许延迟);
    
    尝试容纳任意延迟事件不是一个好主意,因为这样做需要无限期地为每个延迟事件保留一些状态

    改用处理时间计时器怎么样?

    当然,那是
            @Override
            public void processElement2(TaxiFare fare, Context context, Collector<Tuple2<TaxiRide, TaxiFare>> out) throws Exception {
                TimerService service = context.timerService();
                System.out.println("fare time service current watermark ===> " + service.currentWatermark() + "; timestamp ===>" + context.timestamp());
                TaxiRide ride = rideState.value();
                System.out.println("fare state ===> " + ride);
                if (ride != null) {
                    System.out.println("ride is not null ===> " + ride.rideId);
                    rideState.clear();
                    context.timerService().deleteEventTimeTimer(ride.getEventTime());
                    out.collect(new Tuple2(ride, fare));
                } else {
                    System.out.println("update fare state ===> " + fare.rideId + "===>" + context.timestamp());
                    fareState.update(fare);
                    System.out.println(fareState.value() + "===>" + fareState.value().getEventTime());
                    // as soon as the watermark arrives, we can stop waiting for the corresponding ride
                    context.timerService().registerEventTimeTimer(fare.getEventTime());
                }
            }
    
    fare time service current watermark ===> -9223372036854775808; timestamp ===>1356998400000
    fare time service current watermark ===> -9223372036854775808; timestamp ===>1356998400000
    fare state ===> null
    fare state ===> null
    update fare state ===> 26===>1356998400000
    update fare state ===> 58===>1356998400000
    58,2013000058,2013000058,2013-01-01 00:00:00,CRD,2.0,0.0,27.0===>1356998400000
    26,2013000026,2013000026,2013-01-01 00:00:00,CRD,2.0,0.0,12.5===>1356998400000
    fare time service current watermark ===> -9223372036854775808; timestamp ===>1356998400000
    fare state ===> null
    update fare state ===> 9===>1356998400000
    fare time service current watermark ===> -9223372036854775808; timestamp ===>1356998400000
    fare state ===> null
    update fare state ===> 47===>1356998400000
    9,2013000009,2013000009,2013-01-01 00:00:00,CRD,1.0,0.0,6.0===>1356998400000
    47,2013000047,2013000047,2013-01-01 00:00:00,CRD,0.9,0.0,5.9===>1356998400000
    fare time service current watermark ===> -9223372036854775808; timestamp ===>1356998400000
    fare state ===> null
    update fare state ===> 54===>1356998400000
    fare time service current watermark ===> -9223372036854775808; timestamp ===>1356998400000
    54,2013000054,2013000054,2013-01-01 00:00:00,CSH,0.0,0.0,31.0===>1356998400000