如何只处理最后的、最相关的事件(当延迟增长太快时跳过其他事件)?

wnrlj8wa  于 2021-06-07  发布在  Kafka
关注(0)|答案(1)|浏览(263)

上下文:处理来自Kafka的数据并将结果发送回Kafka。
问题:处理每个事件可能需要几秒钟(正在进行改进)。在此期间,事件(和rdd)确实会累积。不必处理中间事件(按键),只需处理最后的事件。因此,当一个进程完成时,理想情况是spark streaming跳过所有不是当前最后一个(按键)的事件。
我不确定这个解决方案是否只能使用spark流api。据我所知,spark streaming,dstream rdd会一个接一个地积累和处理,如果以后还有其他的就不考虑了。
可能的解决方案:
只使用Spark流api,但我不知道如何。 updateStateByKey 似乎是个解决办法。但我不确定当dstream rdd累积时它是否能正常工作,并且您只能按键处理lasts事件。
有两个Spark流管道。一种是按键获取最后更新的事件,将其存储在Map或数据库中。第二个管道仅当事件是另一个管道指示的最后一个事件时才处理这些事件。子问题:
两条管道能共用吗 sparkStreamingContext 以不同的速度处理相同的数据流(低处理与高处理)?
在不使用外部数据库的情况下,是否可以轻松地在管道之间共享值(例如Map)?我认为累加器/广播可以工作,但在两条管道之间我不确定。

fcg9iug3

fcg9iug31#

考虑到流是一个连续的过程,很难定义“最后”在这种情况下的含义。但是,假设您希望在给定的时间段内处理最后一个事件,例如,每10秒运行一次处理,并且在这10秒的帧中只获取每个键的最后一个事件—有两种可能的方法。

窗口进近

其中一个选择是在 DStream :

val windowStream = dStream.window(Seconds(10), Seconds(10))
windowStream.forEachRDD { /* process only latest events */ }

在这种情况下,WindowsStream将具有rdd,该rdd组合了过去10秒内所有rdd中的键/值,您可以在中访问所有这些键/值 forEachRDD 就像你一开始就把它们放在一个rdd里。缺点是它不会提供任何关于事件如何进入流的排序信息,但是您可以在值中包含事件时间信息,或者重用kafka的偏移量

updatestatebykey方法

基本上就像你建议的那样-它可以让你积累价值。databricks提供了一个很好的例子来说明如何做到这一点
在本例中,当它们进行累加时,您可以只更新键的值

Kafka原木压实

虽然这并不能取代在spark端处理它的需要,但如果您在kafka中保留事件一段时间,您可能需要考虑使用kafka的日志压缩,它不能保证重复项不会从kafka进入spark流,但通过只在日志尾部保留最新的密钥,可以减少kafka中存储的事件数。

相关问题