我有一个高度并行化的聚合,我在多个节点上运行了很多键。然后,我想要对所有值进行汇总聚合,类似于下面的代码:
val myStream = sourceStream
.keyBy( 0 )
.window(TumblingProcessingTimeWindows.of(Time.minutes(5)))
.reduce(_ + _)
.addSink(new OtherSink)
val summaryStream = myStream
.map(Row.fromOtherRow(_))
// parallelism is 1 by definition
.windowAll(TumblingProcessingTimeWindows.of(Time.minutes(5)))
.reduce(_ + _)
.addSink(new RowSink)
这很好用,但我注意到最终执行windowAll()的节点会获得大量的入站网络流量以及该节点CPU的显着峰值。这显然是因为所有数据都聚合在一起,并行性为“1”。
Flink中是否有任何当前或计划的条款可以执行更多的双层汇总聚合,以保留每个节点上的所有数据,在将结果发送到第二层以进行最终聚合之前预先聚合它?这是我希望找到的一些伪代码:
val myStream = sourceStream
.keyBy( 0 )
.window(TumblingProcessingTimeWindows.of(Time.minutes(5)))
.reduce(_ + _)
.addSink(new OtherSink)
val summaryStream = myStream
.map(Row.fromOtherRow(_))
// parallelism would be at the default for the env
.windowLocal(TumblingProcessingTimeWindows.of(Time.minutes(5)))
.reduce(_ + _)
// parallelism is 1 by definition
.windowAll(TumblingProcessingTimeWindows.of(Time.minutes(5)))
.reduce(_ + _)
.addSink(new RowSink)
我称之为'windowLocal()',但我相信可能有一个更好的名字。它就像windowAll()一样是非键控的。关键的好处是它可以减少网络和CPU和内存命中windowAll(),通过在您运行的所有节点上分配它。我目前必须为节点分配更多资源以适应此摘要。
如果可以通过当前版本以其他方式实现,我很乐意听到它。我已经考虑过为第二层的密钥使用随机值,但我相信这会导致数据的完全重新平衡,因此它解决了我的CPU和内存问题,而不是网络问题。我正在寻找与rescale()相同的东西,其中数据保持在任务管理器或插槽的本地。
答案 0 :(得分:0)
使用FoldFunction进行增量窗口聚合
以下示例显示了如何将增量FoldFunction与WindowFunction结合以提取窗口中的事件数,并返回窗口的键和结束时间。
val input: DataStream[SensorReading] = ...
input
.keyBy(<key selector>)
.timeWindow(<window assigner>)
.fold (
("", 0L, 0),
(acc: (String, Long, Int), r: SensorReading) => { ("", 0L, acc._3 + 1) },
( key: String,
window: TimeWindow,
counts: Iterable[(String, Long, Int)],
out: Collector[(String, Long, Int)] ) =>
{
val count = counts.iterator.next()
out.collect((key, window.getEnd, count._3))
}
)
使用ReduceFunction进行增量窗口聚合
以下示例显示了如何将增量ReduceFunction与WindowFunction结合使用,以返回窗口中的最小事件以及窗口的开始时间。
val input: DataStream[SensorReading] = ...
input
.keyBy(<key selector>)
.timeWindow(<window assigner>)
.reduce(
(r1: SensorReading, r2: SensorReading) => { if (r1.value > r2.value) r2 else r1 },
( key: String,
window: TimeWindow,
minReadings: Iterable[SensorReading],
out: Collector[(Long, SensorReading)] ) =>
{
val min = minReadings.iterator.next()
out.collect((window.getStart, min))
}
)
你想要更多看到这里
enter code here
https://ci.apache.org/projects/flink/flink-docs-release-1.2/dev/windows.html