如何推迟Spark/RabbitMQ中的事件

如何推迟Spark/RabbitMQ中的事件,rabbitmq,spark-streaming,Rabbitmq,Spark Streaming,我们正在设计一个系统,该系统将使用RabbitMQ(可能稍后的kafka)和spark流传输来传输事件。一些或我们的活动已被分为几个活动类型,因此不要有太大的活动。这意味着某些事件必须等待其他事件(具有相同id)。在特定事件的所有事件到达之前,我们无法继续处理 是否有办法将事件的处理延迟到spark streaming中的下一个处理窗口(如果其他事件尚未到达) 谢谢 Nir从架构的角度来看,有一些问题需要考虑: 您如何确定所有事件都已到达 如果一个事件丢失会发生什么 如果事件不按顺序发生会发生

我们正在设计一个系统,该系统将使用RabbitMQ(可能稍后的kafka)和spark流传输来传输事件。一些或我们的活动已被分为几个活动类型,因此不要有太大的活动。这意味着某些事件必须等待其他事件(具有相同id)。在特定事件的所有事件到达之前,我们无法继续处理

是否有办法将事件的处理延迟到spark streaming中的下一个处理窗口(如果其他事件尚未到达)

谢谢
Nir

从架构的角度来看,有一些问题需要考虑:

  • 您如何确定所有事件都已到达
  • 如果一个事件丢失会发生什么
  • 如果事件不按顺序发生会发生什么?最后一个和第一个相似
原则上,将事件分解为最初作为一个整体形成的部分似乎会增加复杂性并影响系统的可靠性

无论如何,为了回答这个问题,自Spark 1.6.x以来,引入了一个新的有状态流函数:
mapWithState
mapWithState
允许您保留每个键的状态信息,并发出零个或多个相同或不同类型的事件以响应传入事件

应用于这种情况,我们可以将状态建模为
state[PartialEvent]
:当事件进入时,它们被组装到
PartialEvent
对象中。一旦满足了事件完成的条件,mapWithState就可以生成一个要在下游处理的
WholeEvent
对象

该过程大致如下所示:

val sourceEventDStream:DStream[Event] = ???
def stateUpdateFunction(eventId:String, event: Event, partialEventState: State[PartialEvent]): Option[WholeEvent] = {
    val eventState = partialEventState.get()  // Get current state of the event
    val updatedEvent = merge(eventState, event)
    if (updatedEvent.isComplete) {
       partialEventState.remove()
       Some(WholeEvent(updatedEvent)) 
    }  else {
       partialEventState.update(updatedEvent)
       None
    }          
}
val wholeEventDStream:DStream[WholeEvent] = sourceEventDStream.mapWithState(StateSpec.function(stateUpdateFunction))
//do stuff with wholeEventDStream ...
正如您所观察到的,使用这种方法,任何永远不会完成的
PartialEvent
都将永远处于该状态。我们还需要一个唯一的键来识别属于一起的事件。必须考虑超时选项来覆盖故障情况,但底线是,如果技术上可行,通过管道保存整个事件将是一种更好的方法



(*)未编译或测试。仅用于说明这一想法。

我使用rabbitmq的目的不同,因此这可能会有帮助,也可能没有帮助,请查看DLX(死信交换)您可以通过发布到此队列来延迟,当它们再次到达时,您可以继续决定是否应该再次处理它们;您正在将事件A拆分为事件1、事件2..eventAn;在处理eventAn-1之前,您无法处理eventAn。如果这是正确的,为什么要首先拆分eventA?你说它很大,这是什么意思?要降低网络传输速度?