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

时间:2017-05-26 19:18:11

标签: apache-flink flink-streaming

我正在尝试利用并行性来加速Top-10窗口操作。我的应用程序包含具有时间戳和密钥的事件(即Tuple2<Long,String>),我的目标是为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);

以上是解析CSV文件中的数据并分配事件时间(即Ingress)的代码。我将并行性设置为1的原因是因为我需要事件显示为有序,以便我可以将它们分配给窗口。

接下来是棘手的部分,我尝试在生成正确(和有序)窗口结果的同时加快执行速度。

天真(连续)执行

以下代码提供了一种不使用任何并行性并生成串行流的解决方案:

DataStream<Tuple2<Long, String>> windowedTopTen = s
        .windowAll(TumblingEventTimeWindows.of(Time.minutes(30)))
        .apply(new SerialAggregation()).setParallelism(1);

其中SerialAggregation扩展RichAllWindowFunction<Tuple3<Long, String, Integer>, Tuple2<Long, String>, TimeWindow>,每个翻滚窗口Tuple2<Long, String>Long是时间戳,String包含前10个键)。

朴素的方法产生正确的结果,结果数据流按升序时间戳排序。不幸的是,它没有利用多线程,因此当输入数据是一些GB时,执行需要一段时间才能完成。

平行(更快)方法

在查看Flink关于Windows的文档后,我试图通过使用parallelism > 1来实现前10个示例的更智能方法,同时为每个窗口生成正确的结果。因此,我发现我需要将s转换为KeyedStream,然后应用window()转换。实质上:

DataStream<Tuple2<Long, String>> windowedTopTen = s
    .keyBy(1)
    .window(TumblingEventTimeWindows.of(Time.minutes(30)))
    .apply(new PartialAggregation()).setParallelism(N);

其中PartialAggregation()将为不同的时间戳产生(不相交的密钥集)的部分结果。换句话说,我的理解是,对于相同的时间戳t1,我最终会partial_result_1partial_result_N,其中N是我设置的并行度。我的目标是聚合特定时间戳的所有部分结果(如t1),但我不知道该怎么做。此外,当我能够将部分结果与匹配的时间戳组合时,我将如何生成数据流,其元组基于时间戳排序(如朴素解决方案生成的结果)。

问题

  1. 如何完成并行(更快)方法以产生所需结果并将部分结果与匹配的时间戳结合起来?
  2. 在我为每个时间戳组合部分结果后,是否有办法生成数据流,其中结果按时间戳排序?

1 个答案:

答案 0 :(得分:1)

首先,如果用Tuple3替换你的Tuple3,其中String是单个键,并且整数是计数器,那么将部分前10个结果组合到整个前10个中会更容易

然后你可以使用windowAll和聚合窗口函数来处理第二层窗口,该函数保留前10个键(整体)及其计数。