Java 在Flink中处理后,将元素传递回输入流?

Java 在Flink中处理后,将元素传递回输入流?,java,apache-flink,flink-streaming,amazon-kinesis,amazon-kinesis-analytics,Java,Apache Flink,Flink Streaming,Amazon Kinesis,Amazon Kinesis Analytics,场景: 我有一个来自传感器的事件流。事件可能为T型或J型 T型事件具有事件发生时间戳 J型事件具有开始和结束时间戳 根据J-Type事件的开始和结束时间戳,对时间范围内的所有T-Type事件应用聚合逻辑,并将结果写入数据库 为此,我创建了一个自定义触发器,它在接收到J-Type事件时被触发。在自定义ProcessWindowFunction中,我正在执行聚合逻辑和时间检查 但是,可能存在这样一种情况,T型事件不在当前J型事件的时间范围内。 在这种情况下,在清除当前窗口之前,应将T型事件推送到

场景:

我有一个来自传感器的事件流。事件可能为T型J型

  • T型事件具有事件发生时间戳
  • J型事件具有开始和结束时间戳
根据J-Type事件的开始和结束时间戳,对时间范围内的所有T-Type事件应用聚合逻辑,并将结果写入数据库

为此,我创建了一个自定义触发器,它在接收到J-Type事件时被触发。在自定义ProcessWindowFunction中,我正在执行聚合逻辑和时间检查

但是,可能存在这样一种情况,T型事件不在当前J型事件的时间范围内。 在这种情况下,在清除当前窗口之前,应将T型事件推送到下一个窗口

思考解决方案:

  • 在自定义窗口处理函数中,将未处理的T型事件推送到Kinesis流(源)中。(最坏情况解决方案)

  • 不要使用FIRE和PURGE,而是使用FIRE在整个运行时保持状态。使用元素迭代器删除已处理的元素。(不推荐,以保持无限窗口)

  • 我想知道,是否有任何方法可以直接将未处理的事件推回到输入流(不带动画)。(重新排队)


    有没有办法在keyBy上下文中维护状态,以便我们对这些未处理的数据(在或之前)以及窗口元素执行计算。

    以下是两种解决方案。它们的基本行为或多或少是相同的,但您可能会发现其中一个更容易理解、维护或测试

    至于你的问题,不,没有办法循环(重新排队)未使用的事件,而不将它们推回到运动状态。但只要坚持到需要它们,就可以了

    解决方案1:使用RichFlatMapFunction

    当T型事件到达时,将它们附加到
    ListState
    对象。当J-type事件到达时,将列表中所有匹配的T-type事件收集到输出,并更新列表以仅保留将属于后续J-type事件的T-type事件

    解决方案2:使用带有自定义触发器和逐出器的全局Windows

    除了您已经完成的操作之外,实现一个
    逐出器
    ,该逐出器(在启动窗口后)仅从窗口中移除J-type事件和所有匹配的T-type事件

    更新:清除过期钥匙/失效传感器的状态

    对于解决方案1,您可以使用来安排清除与失效密钥关联的任何非活动状态。或者您可以使用
    KeyedProcessFunction
    而不是
    RichFlatMapFunction
    ,并使用计时器来完成同样的任务


    使用窗口API管理过期键的状态可能不那么简单,但对于解决方案2,我相信您可以扩展自定义触发器,使其包含一个将清除窗口的超时。如果您在
    ProcessWindowFunction
    中使用了全局状态,则需要依赖状态TTL来清除该问题。

    在讨论解决方案之前,我想更好地了解该问题。T和J事件是否在同一个流中?那个流是通过什么(可能是通过sensorId)键控的?您解释了如何同时有两个打开的窗口。事情有多混乱?可能同时有三个或更多打开的窗口吗?窗口的J事件是否总是在T事件之前(或之后),或者是否可以进行任何排序。是的,他们在同一条小溪里。2.是的,流是keyBy(“sensorId”)。3.同一个“sensorId”不会同时有两个打开的窗口。第一个窗口在我们收到第一个J-Type后关闭。然后第二个窗口打开。这里,J-Type启动窗口触发器。在窗口1中,我们还可以接收T-type,它应该属于后续窗口。我们根据T-type事件中发生的事件时间戳,将T-type事件关联到J-type事件。如果事件发生时间戳落在J-Type时间范围内,则它属于该J-Type。如果不在时间范围内,则应将这些t型事件推送到下一个窗口,以检查其是否在该窗口中有效。处理引擎通常根据有向无环图或DAG来考虑流程管道。这是处理可以按特定顺序遍历函数的地方,函数可以链接在一起,但处理决不能返回到图中的较早点。从此以后,重新排队不再是一种策略。使用
    ListState
    作为我当前场景的解决方案。嘿,大卫,谢谢你的回复。我对window的理解是,他们是Akka演员。如果传感器失效,
    sensorId
    将过时。因此,如果我们没有针对windows的清除策略,这些过时的参与者将消耗主内存。在我们的情况下,重新排队是唯一最好的解决方案,因为它简化了流程,并减少了死角情况。如果有任何方法可以直接将文件发送回输入流(不带kinesis),那么请分享这种方法。我也在考虑使用一个附加流(kinesis或任何其他建议),它将从exector()接收这些无效元素,并与主输入流合并()。请分享您的想法?我非常喜欢解决方案1(有状态平面图或进程函数);这就是我要做的。我不知道重新排队如何解决传感器失效的问题。你可能会在最后几次T型比赛中无休止地回到动觉状态。