基于以前由批处理(火花)作业保存的数据,如何通过不带窗口的新流应用程序(flink / beam)“仅一次”增量/更新

时间:2018-09-30 07:14:06

标签: apache-flink apache-beam

我有一个批处理/火花应用程序,该应用程序将sqoop / mysql数据作为快照读取,并基于所有历史数据进行大量统计,并将结果写入mongodb。

如您所知,请确保以大约1.5小时的间隔在批处理/脱机模式下生成mongodb结果。

现在我的老板要求我将所有结果实时转换,所以我考虑使用流式系统来做到这一点。我的第一个想法是将mysql总数据转换为kafka msgs,然后使用流技术之一sparkstreaming / flink / beam进行操作。但是经过尝试,将所有数据作为味精转换并发送到kafka确实时间太长,尤其是当我更改了流应用程序的逻辑并且不得不再次发送数据时,如果不是发送完整的数据集,很难分辨如果我的流式传输结果与批处理相比是正确的。

还有另一个问题,在我的情况下,我没有窗口,只是所有历史数据都被过滤并像多维数据集一样求和/计数。流系统确实支持我所需要的全局窗口,但是对接收器/数据库的写入必须由“触发器”调用,这对我来说就像一个计时器,然后又不是实时的,这是违反了使用流系统的初衷。

全局窗口的想法也像批处理作业一样具有拥抱内存。

所以我想也许我可以通过一个新的流应用程序(flink / beam)实时增加/更新由批处理作业保存的mongodb数据,这将消耗更少的内存/ cpu,并且每次到达时都会更新数据新的流媒体元素,也许以这种方式是“实时”的。

但是我检查了流式flink / beam程序指南,就像我的情况要转到无状态目录一样,我必须自己做incr / update的反工作。例如flink,我必须在flink的asynchronos I / O或tableink API中实现它。我自己可以做,但我有一个担心,因为当作业/任务失败时,所有流系统都具有这种“精确一次”机制,可以在流拓扑/ dag内全部回复/重新发送流元素其中障碍(flink)之间。那么如果这些元素重新发送,那么结果将被写入mongodb两次?

这种担忧促使我对flink / beam的源代码进行了更深入的研究(据说火花流在延迟方面不太好,因为它比纯流系统多了很多)。幸运的是我找到了flink \ flink-connectors \ flink-connector-cassandra \ src \ main \ java \ org \ apache \ flink \ streaming \ connectors \ cassandra \ CassandraRowWriteAheadSink.java 看起来像使用此接收器,fink可以在“屏障”提交成功之前缓冲元素。

我仍然有疑问: 1,是否是我将上述cassandra接收器移植到mongodb以基于批处理结果完全填充incr / update的唯一/最佳方法? 2,无论如何要在Beam中利用WriteAhead机制,因为我在Beam(beam \ sdks \ java \ io \ mongodb \ src \ main \ java \ org \ apache \ beam \ sdk \ io \ mongodb \ MongoDbIO中找不到类似的实现.java)? 因为我喜欢在运行程序(spark,flink)中运行应用程序的Beam想法,现在我正在开发一个Spark Ba​​tch应用程序和新的Fink Streaming应用程序。后来我不想再努力了。我想用Beam编写应用程序并在spark上批量运行它(我不太担心flink的批处理性能,因为它很少用于批生产中?),并在flink中进行流式处理。为什么不对批次和流进行flink,有些人可能会问。这是由于我个人对SQL以外的API的偏爱,因为flink只能按表API针对批处理/流重用代码,但是那些表API更多的是纯SQL而不是spark数据帧API的API方式更多,而无需格式化作为条件的SQL语句,如果您的要求是动态过滤字段中的大量动态总和/计数目标。

0 个答案:

没有答案