Apache flink 如何在ApacheFlink中将批处理数据刷新到接收器

Apache flink 如何在ApacheFlink中将批处理数据刷新到接收器,apache-flink,Apache Flink,我使用apache flink(v1.10.0)计算RabbitMQ消息,将结果接收到MySQL,现在我的计算方式如下: consumeRecord.keyBy("gameType") .timeWindowAll(Time.seconds(5)) .reduce((d1, d2) -> { d1.setRealPumpAmount(d1.getRealPumpAmount() +

我使用apache flink(v1.10.0)计算RabbitMQ消息,将结果接收到MySQL,现在我的计算方式如下:

   consumeRecord.keyBy("gameType")
                .timeWindowAll(Time.seconds(5))
                .reduce((d1, d2) -> {
                    d1.setRealPumpAmount(d1.getRealPumpAmount() + d2.getRealPumpAmount());
                    d1.setPumpAmount(d1.getPumpAmount() + d2.getPumpAmount());
                    return d1;
                })
                .addSink(new SinkFunction<ReportPump>() {
                    @Override
                    public void invoke(ReportPump value, Context context) throws Exception {
                        // save to mysql
                    }
                });
consumerrecord.keyBy(“游戏类型”)
.timeWindowAll(时间秒(5))
.减少((d1,d2)->{
d1.setRealPumpAmount(d1.getRealPumpAmount()+d2.getRealPumpAmount());
d1.setPumpAmount(d1.getPumpAmount()+d2.getPumpAmount());
返回d1;
})
.addSink(新的SinkFunction(){
@凌驾
公共void调用(ReportPump值、上下文)引发异常{
//保存到mysql
}
});
但是现在sink方法在每次调用中只获取一行,如果此批处理中的一行失败,我无法回滚批处理操作。现在我想获取一个窗口的批处理并将其接收到数据库一次,如果失败,我回滚insert和Apache Flink的检查点。这就是我现在要做的:

consumeRecord.keyBy("gameType")
                .timeWindowAll(Time.seconds(5)).reduce(new ReduceFunction<ReportPump>() {
                    @Override
                    public ReportPump reduce(ReportPump d1, ReportPump d2) throws Exception {
                        d1.setRealPumpAmount(d1.getRealPumpAmount() + d2.getRealPumpAmount());
                        d1.setPumpAmount(d1.getPumpAmount() + d2.getPumpAmount());
                        return d1;
                    }
                })
                .apply(new AllWindowFunction<ReportPump, List<ReportPump>, TimeWindow>() {
                    @Override
                    public void apply(TimeWindow window, Iterable<ReportPump> values, Collector<List<ReportPump>> out) throws Exception {
                        ArrayList<ReportPump> employees = Lists.newArrayList(values);
                        if (employees.size() > 0) {
                            out.collect(employees);
                        }
                    }
                })
                .addSink(new SinkFunction<List<ReportPump>>() {
                    @Override
                    public void invoke(List<ReportPump> value, Context context) throws Exception {
                        PumpRealtimeHandler.invoke(value);
                    }
                });
consumerrecord.keyBy(“游戏类型”)
.timeWindowAll(Time.seconds(5)).reduce(新的ReduceFunction(){
@凌驾
公共报告泵减少(报告泵d1、报告泵d2)引发异常{
d1.setRealPumpAmount(d1.getRealPumpAmount()+d2.getRealPumpAmount());
d1.setPumpAmount(d1.getPumpAmount()+d2.getPumpAmount());
返回d1;
}
})
.apply(新的AllWindowFunction(){
@凌驾
公共void apply(时间窗口、Iterable值、收集器输出)引发异常{
ArrayList employees=Lists.newArrayList(值);
如果(employees.size()>0){
出、收(员工);
}
}
})
.addSink(新的SinkFunction(){
@凌驾
公共void调用(列表值、上下文)引发异常{
调用(值);
}
});

但是apply函数给出提示:
无法解析“SingleOutputStreamOperator”中的方法“apply”
。如何减少它并获取批处理数据列表并只刷新到数据库一次?

SingleOutputStreamOperator并没有应用方法,因为应用只能在窗口打开后发出。 你在这里错过的是:

.windowAll(GlobalWindows.create())
在reduce和apply之间,它会将所有简化结果聚合到一个全局窗口中,该窗口包含所有简化结果的列表,这样您就可以针对数据库对一个列表而不是多个批进行收集


我不知道你的结果是否是一个好的实践,因为你将失去ApacheFlink的并行性

您应该阅读有关TableApi和JDBC接收器的内容,也许它会对您有所帮助。(有关详细信息,请参见此处:)