崩溃时在Persistent Actor中丢失事件发布

时间:2019-05-24 10:58:33

标签: akka lagom akka-persistence

在此示例中,来自Akka persistance documentation

    val receiveRecover: Receive = {
    case evt: Evt                                 => updateState(evt)
    case SnapshotOffer(_, snapshot: ExampleState) => state = snapshot
    }

    val snapShotInterval = 1000
    val receiveCommand: Receive = {
    case Cmd(data) =>
      persist(Evt(s"${data}-${numEvents}")) { event =>
        updateState(event)
        context.system.eventStream.publish(event)
        if (lastSequenceNr % snapShotInterval == 0 && lastSequenceNr != 0)
          saveSnapshot(state)
      }
    case "print" => println(state)
    }

我了解这个lambda:

    event =>
    updateState(event)
    context.system.eventStream.publish(event)
    if (lastSequenceNr % snapShotInterval == 0 && lastSequenceNr != 0)
      saveSnapshot(state)

在事件成功持久后执行。 如果在成功执行事件之前(即在context.system.eventStream.publish(event)之前)执行lambda时演员崩溃了?

我是否正确理解在这种情况下事件从未发布过,这可能导致系统状态不一致?如果是这样,有什么方法可以检测到发生这种情况吗?

[编辑]

此外,如果您在系统中使用事件发布,那么如果我错了,请纠正我:

  1. 如果您的应用程序部署在一个JVM中,并且使用默认的Akka事件发布工具,那么JVM崩溃将意味着所有已发布但尚未处理的事件都将丢失,因为该工具没有任何恢复机制。

  2. 如果您的应用程序部署在群集中,则只有在整个群集关闭时,您才可以在与上述相同的情况下运行。

  3. 对于任何生产设置,都应配置类似Kafka的功能以进行事件发布/使用。

1 个答案:

答案 0 :(得分:0)

  

我了解这个lambda:

     

...

     

在事件成功持久后执行。如果   在执行此lambda之前,演员崩溃   成功发布事件,即之前   context.system.eventStream.publish(event)?

lambda在状态保持后运行。演员基本上会暂停自己的工作(将所有待处理的工作放在隐藏处),直到完成持久性,以便保持一致。

  

我是否正确理解在这种情况下该事件永远不会   会导致系统状态不一致?

否,由于上述原因,它将保持一致。

  

如果您的应用程序部署在一个JVM中,并且使用默认的Akka事件发布工具,那么JVM崩溃将意味着所有已发布但尚未处理的事件都将丢失,因为该工具没有任何恢复机制。

我想这取决于您默认事件发布的含义。常规演员,是的。如果您丢失了JVM,则将失去“常规”参与者。常规角色在内存中,就像普通的Java / Scala对象一样。坚持不懈的演员当然是另外一个故事。

您还说“已发布但尚未处理”。这些当然也丢失了。任何未“处理”的事物本质上都像是数据库尚未接收到的JDBC语句,或者消息未传输给Kafka等。该设计本质上是将事件立即保存到数据库中(几乎像交易日志),然后在已知可以安全保存之后进行工作。

  

如果您的应用程序部署在群集中,则只有在整个群集出现故障时,您才可以在与上述相同的情况下运行。

集群实际上只是为持久参与者提供了恢复的场所。群集仍依赖持久性存储进行恢复。

(我将答案集中在Akka永久演员上,答案随着诸如分布式数据之类的东西而变得更加多样化。)

  

对于任何生产设置,您都应配置诸如Kafka之类的功能以进行事件发布/使用。

不一定。持久模块绝对是一个一致的选择。 Kafka和Akka实际上只是具有不同目标的不同动物。 Kafka实际上是发布/订阅,Akka本质上采用了更多的事件源方法。我曾经使用过这两种系统,但是它们将它们用于不同的目的。