在Apache FLink中计算不同窗口上的指标

时间:2017-03-28 14:03:29

标签: java apache-flink

我正在使用Apache Flink 1.2,这是我的问题: 我有一个数据流,我想在1天的窗口内计算一个指标。因此我会写一些类似的东西:

DataStream<Tuple6<Timestamp, String, Double, Double, Double, Integer>> myStream0 = 
            env.readTextFile("Myfile.csv")
            .map(new MyMapper())                // Parse the input
            .assignTimestampsAndWatermarks(new MyExtractor())   //Assign the timestamp of the event 
            .timeWindowAll(Time.days(1))    
            .apply(new average());  // compute average, max, sum

现在我想在1小时的窗口内计算相同的指标。

我可以像以前一样编写并指定Time.hours(1),但我担心的是,这样apache flink读取输入文件的两倍并完成两倍的工作。我想知道是否有办法做所有的事情(即使用相同的流)。

1 个答案:

答案 0 :(得分:0)

您可以计算每小时聚合以及每日聚合。这将寻找一个简单的DataStream<Double>,如下所示:

DataStream<Double> vals = ... // source + timestamp extractor

DataStream<Tuple2<Double, Long>> valCnt = vals // (sum, cnt)
  .map(new CntAppender())     // Double -> Tuple2<Double, Long(1)>

DataStream<Tuple3<Double, Long, Long>> hourlySumCnt = valCnt // (sum, cnt, endTime)
  .timeWindowAll(Time.hours(1))
  // SumCounter ReduceFunction sums the Double and Long field (Long is Count)
  // WindowEndAppender WindowFunction adds the window end timestamp (3rd field)
  .reduce(new SumCounter(), new WindowEndAppender())   

DataStream<Tuple2<Double, Long>> hourlyAvg = hourlySumCnt // (avg, endTime)
  .map(new SumDivCnt()) // MapFunction divides Sum by Cnt for average

DataStream<Tuple3<Double, Long, Long>> dailySumCnt = hourlySumCnt // (sum, cnt, endTime)
  .map(new StripeOffTime()) // removes unnecessary time field -> Tuple2<Double, Long>
  .timeWindowAll(Time.days(1))
  .reduce(new SumCounter(), new WindowEndAppender()) // same as above

DataStream<Tuple2<Double, Long>> dailyAvg = dailySumCnt // (avg, endTime)
  .map(new SumDivCnt()) // same as above

因此,您基本上计算每小时的总和和计数,并根据该结果

  1. 计算每小时平均值
  2. 计算每日总和和计数以及每日平均值
  3. 注意,我使用ReduceFunction代替WindowFunction进行总和和计数计算,因为急切应用ReduceFunction,即窗口的所有记录都不是收集但立即汇总。因此,需要维护的状态是单一记录。