Java ApacheFlink将结果减少为多个值,而不是一个值

Java ApacheFlink将结果减少为多个值,而不是一个值,java,apache,bigdata,apache-flink,flink-streaming,Java,Apache,Bigdata,Apache Flink,Flink Streaming,我正在尝试在WindowedStream上实现reduce,如下所示: .keyBy(t -> t.key) .timeWindow(Time.of(15, MINUTES), Time.of(1, MINUTES)) .reduce(new ReduceFunction<TwitterSentiments>() { @Override

我正在尝试在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;
                }
            });
.keyBy(t->t.key)
.时间窗口(时间(15分钟),时间(1分钟))
.reduce(新的ReduceFunction(){
@凌驾
公共推特情感减少(推特情感t2,推特情感t1)抛出异常{
t2.阳性+=t1.阳性;
t2.中性+=t1.中性;
t2.阴性+=t1.阴性;
返回t2;
}
});
我遇到的问题是,当我调用stream.print()时,我会得到许多值(看起来像是每个TwitterMotions对象一个值,而不是一个聚合对象)

我也尝试过使用这样的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);
                }
            });
.aggregate(新的AggregateFunction(){
@凌驾
公共元组3 createAccumulator(){
返回新的Tuple3(0L,0L,0L);
}
@凌驾
公共Tuple3添加(twitter、Tuple3累加器){
返回新的Tuple3(
累加器.f0+ts.positive.longValue(),
累加器.f1+ts.neutral.longValue(),
累加器.f2+ts.negative.longValue()
);
}
@凌驾
公共Tuple3 getResult(Tuple3累加器){
回流蓄能器;
}
@凌驾
公共Tuple3合并(Tuple3累加器1、Tuple3累加器2){
返回新的Tuple3(
蓄能器1.f0+蓄能器2.f0,
蓄能器1.f1+蓄能器2.f1,
蓄能器1.f2+蓄能器2.f1);
}
});

stream.print()的原因是什么在这些聚合之后仍然会输出许多记录吗?

似乎我误解了使用键的原因。在我的情况下,我不需要
KeyedStream
,因为我希望每分钟只有一个输出,它包含所有减少到一个值的记录。我最终在
单输出上使用了
.timeWindowAll
utStreamOperator
,运行my reduce现在可以按预期工作。

如果不需要每个键的结果,可以使用timeWindowAll生成单个结果。但是,timeWindowAll不会并行运行。如果要以更可伸缩的方式计算结果,可以执行以下操作:

    .keyBy(t -> t.key)
    .timeWindow(<time specification>)
    .reduce(<reduce function>)
    .timeWindowAll(<same time specification>)
    .reduce(<same reduce function>)
.keyBy(t->t.key)
.timeWindow()
.reduce()
.timeWindowAll()
.reduce()

您可能希望Flink的运行时足够智能,可以为您执行此并行预聚合(前提是您使用的是ReduceFunction或AggregateFunction),但事实并非如此。

您可能正在使用
EventTime
。您能为流媒体环境检查
timeCharacteristic
的设置吗(由环境设置流时间特性设置)?如果您使用的是
EventTime
,那么时间窗口是由事件时间而不是本地机器时间触发的。@David Hmm,谢谢您的回答,但这似乎不是问题所在。
timeCharacteristic
默认设置为
ProcessingTime
。我尝试使用
IngestionTime
,但仍然存在相同的问题e、 这里还会发生什么?啊,你能检查一下打印输出的键吗?它们都不同吗?对于同一个键,打印输出的间隔必须超过1分钟(翻滚窗口)。每分钟每个键应该得到一个结果。如果结果中包含键和时间,则更容易理解发生了什么情况——可以通过将预聚合结果传递给ProcessWindowFunction来完成。请参阅示例。@DavidAnderson Ah,“每键”。这是有道理的。你的回答帮助我解决了我的问题。谢谢。这正是我最初试图做的,谢谢。我创建了一个密钥流,因为我想要并行处理,但没有看到密钥流也按密钥聚合。这现在更有意义了。你是对的,我希望flink做这个过程嗨,我用
timeWindow->process->timeWindowAll->reduce
做了一个例子,我想知道我是否可以在Flink中实现我自己的操作符(使用
SingleOutputStreamOperator