如何获取分钟处理窗口的最新记录

时间:2018-10-23 19:29:17

标签: java apache-flink flink-streaming

我有一个使用windows的flink流作业。

我的目标是在一分钟之内将记录按其内部id进行分组,并仅按id逐条记录最新记录。

我想出了两种可能的方法:

  1. 使用reduce()

    stream.keyBy(Record::getId)
        .window(TumblingProcessingTimeWindows.of(Time.seconds(60)))
        .reduce((rec1, rec2) -> rec2);
    

    这很好用,但似乎很浪费,因为它需要每个每个记录。

  2. 使用process()

    stream.keyBy(Record::getId)
        .window(TumblingProcessingTimeWindows.of(Time.seconds(60)))
        .process(new ProcessWindowFunction<Record, Object, Long, TimeWindow>() {
            @Override
            public void process(Long aLong, Context context, Iterable<Record> iterable, Collector<Object> collector) throws Exception {
                Record last = null;
                for (Record rec : iterable) {
                    if (last == null || last.getTimestamp() < rec.getTimestamp()) {
                        last = rec;
                    }
                }
                collector.collect(last);
            }
        });
    

这也可以正常工作。我曾预计它会更快,但它不是(与解决方案1大致相同)。

您能推荐一种更好的方法吗?

1 个答案:

答案 0 :(得分:0)

您的解决方案1.似乎是这里的最佳方法。

关于您的评论:

  

这很好用,但似乎浪费了,因为每条记录都需要调用它。

问题是您不知道哪个记录将是最后一个。因此,您始终需要存储最后看到的记录。由于ReduceFunction的结果存储在状态中(用于方法的下一次评估或将其作为结果返回),所以这正是这里发生的情况。

您的解决方案2实际上(从存储/内存的角度来看)效率较低。它会记住在一分钟内到达的所有记录,并在评估窗口时遍历所有记录。相反,解决方案1.仅存储一个值(最后一次函数求值的结果)。

您可以使用常规的ProcessFunction和计时器来实现解决方案,但是,我认为这不会比window + ReduceFunction快得多。而且,这将需要更多代码。