我试图在WindowedStream上实现reduce,就像这样:
.keyBy(t -> t.key)
.timeWindow(Time.of(15, MINUTES), Time.of(1, MINUTES))
.reduce(new ReduceFunction<TwitterSentiments>() {
@Override
public TwitterSentiments reduce(TwitterSentiments t2, TwitterSentiments t1) throws Exception {
t2.positive += t1.positive;
t2.neutral += t1.neutral;
t2.negative += t1.negative;
return t2;
}
});
我遇到的问题是,当我调用stream.print()时,我得到了很多值(每个TwitterSentiments对象看起来像一个值,而不是单个聚合对象。
我也曾尝试使用像这样的AggregationFunction,但存在相同的问题:
.aggregate(new AggregateFunction<TwitterSentiments, Tuple3<Long, Long, Long>, Tuple3<Long, Long, Long>>() {
@Override
public Tuple3<Long, Long, Long> createAccumulator() {
return new Tuple3<Long, Long, Long>(0L,0L,0L);
}
@Override
public Tuple3<Long, Long, Long> add(TwitterSentiments ts, Tuple3<Long, Long, Long> accumulator) {
return new Tuple3<Long, Long, Long>(
accumulator.f0 + ts.positive.longValue(),
accumulator.f1 + ts.neutral.longValue(),
accumulator.f2 + ts.negative.longValue()
);
}
@Override
public Tuple3<Long, Long, Long> getResult(Tuple3<Long, Long, Long> accumulator) {
return accumulator;
}
@Override
public Tuple3<Long, Long, Long> merge(Tuple3<Long, Long, Long> accumulator1, Tuple3<Long, Long, Long> accumulator2) {
return new Tuple3<Long, Long, Long>(
accumulator1.f0 + accumulator2.f0,
accumulator1.f1 + accumulator2.f1,
accumulator1.f2 + accumulator2.f1);
}
});
在这些聚合之后,stream.print()仍会输出许多记录的原因是什么?
答案 0 :(得分:1)
看来我误解了使用键的原因。就我而言,我不需要KeyedStream
,因为我希望每分钟只有一个输出,该输出包括所有记录减少为一个值的记录。我最终在.timeWindowAll
上使用了SingleOutputStreamOperator
,并且运行reduce现在可以正常工作了。
答案 1 :(得分:1)
如果每个键不需要结果,则可以使用timeWindowAll产生单个结果。但是,timeWindowAll不能并行运行。如果要以更可扩展的方式计算结果,可以执行以下操作:
.keyBy(t -> t.key)
.timeWindow(<time specification>)
.reduce(<reduce function>)
.timeWindowAll(<same time specification>)
.reduce(<same reduce function>)
您可能希望Flink的运行时足够聪明,可以为您执行此并行预聚合(前提是您使用的是ReduceFunction或AggregateFunction),但事实并非如此。