Apache flink 利用并行性生成有序窗口聚合(即前10个查询)

Apache flink 利用并行性生成有序窗口聚合(即前10个查询),apache-flink,flink-streaming,Apache Flink,Flink Streaming,我正试图利用并行性来加速前10个窗口操作。我的应用程序由具有时间戳和键和(即,Tuple2)的事件组成,我的目标是为30分钟的翻滚窗口生成前10个最频繁的键(使用事件时间)。为此,我的查询由入口、窗口和聚合阶段组成。换句话说,我的代码需要执行以下操作: DataStream<Tuple3<Long, String, Integer>> s = env .readTextFile("data.csv") .map(new MapFunction<Str

我正试图利用并行性来加速前10个窗口操作。我的应用程序由具有时间戳和键和(即,
Tuple2
)的事件组成,我的目标是为30分钟的翻滚窗口生成前10个最频繁的键(使用事件时间)。为此,我的查询由入口、窗口和聚合阶段组成。换句话说,我的代码需要执行以下操作:

DataStream<Tuple3<Long, String, Integer>> s = env
    .readTextFile("data.csv")
    .map(new MapFunction<String, Tuple3<Long, String, Integer>>() {
      @Override
      public Tuple3<Long, String, Integer> map(String s) throws Exception {
        String[] tokens = s.split(",");
        return new Tuple3<Long, String, Integer>(Long.parseLong(tokens[0]),
            tokens[1], 1);
      }})
    .assignTimestampsAndWatermarks(
        new AscendingTimestampExtractor<Tuple3<Long, String, Integer>>() {
          @Override
          public long extractAscendingTimestamp(Tuple3<Long, String, Integer> t) {
            return t.f0;
          }}).setParallelism(1);
其中,
PartialAggregation()
将为不同的时间戳生成部分结果(不相交的键集)。换句话说,我的理解是,对于相同的时间戳
t1
,我将以
partial\u result\u 1
partial\u result\u N
结束,其中
N
是我设置的并行性。我的目标是聚合特定时间戳的所有部分结果(如
t1
),但我不知道如何做到这一点。另外,当我能够将部分结果与匹配的时间戳相结合时,我将如何生成一个数据流,它的元组是基于时间戳排序的(就像原始解决方案生成的结果一样)

问题

  • 如何完成并行(更快)方法以产生所需结果,并将部分结果与匹配的时间戳相结合
  • 在我为每个时间戳组合部分结果之后,有没有一种方法可以生成一个数据流,其中的结果根据时间戳排序

  • 首先,如果将Tuple2替换为Tuple3,其中字符串是一个键,整数是计数器,那么将部分前10名结果合并到整体前10名将更容易


    然后,您可以使用windowAll和聚合窗口功能添加第二层窗口,该功能保留前10个键(总键数)及其计数。

    谢谢。在周末期间,我提出了(几乎)你的建议:在部分结果并行评估之后,我定义了一个
    windowAll()
    ,然后是一个
    appy()
    ,以组合所有部分结果并得出前十名。此外,我对代码进行了扩展,以包含一个额外的
    Integer
    计数字段。然而,我有一个更重要的问题:在连续运行中,我没有得到可重复的结果。详细地说,在不同的结果中,我没有得到相同数量的窗口。这不应该发生,因为我的数据存储在一个文件中,并且我使用
    EventTime
    。在有限的历史流上使用EventTime时,您需要注意水印是否有意义。如果您使用的是自动水印,那么Flink将尝试每200毫秒生成一次水印,但您的程序有时可能会在运行200毫秒之前运行到完成。您还需要注意提供一个关闭最后一个窗口的水印。再次非常感谢!正如您在源代码中看到的,我一直在使用
    AscendingTimestampExtractor
    ,它似乎对我的用例有意义。通过将parallelism设置为1(对于小于等于
    assignTimestampsAndWatermarks()
    的所有转换),我解决了关于不可再现结果的问题。然而,这让我回到了部分结果的串行执行,因为它们只由1个映射器(输出状态映射器(1/1))处理。如果我正确地理解了Flink,那么在利用并行性的同时,很难确定地处理历史流。对吧?更新我上面的评论,我错了。Flink为部分结果生成多个贴图器。我只是在读旧的日志文件。再次感谢@alpinegizmo的回答和评论。
    DataStream<Tuple2<Long, String>> windowedTopTen = s
            .windowAll(TumblingEventTimeWindows.of(Time.minutes(30)))
            .apply(new SerialAggregation()).setParallelism(1);
    
    DataStream<Tuple2<Long, String>> windowedTopTen = s
        .keyBy(1)
        .window(TumblingEventTimeWindows.of(Time.minutes(30)))
        .apply(new PartialAggregation()).setParallelism(N);