在此示例中,来自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时演员崩溃了?
我是否正确理解在这种情况下事件从未发布过,这可能导致系统状态不一致?如果是这样,有什么方法可以检测到发生这种情况吗?
[编辑]
此外,如果您在系统中使用事件发布,那么如果我错了,请纠正我:
如果您的应用程序部署在一个JVM中,并且使用默认的Akka事件发布工具,那么JVM崩溃将意味着所有已发布但尚未处理的事件都将丢失,因为该工具没有任何恢复机制。
如果您的应用程序部署在群集中,则只有在整个群集关闭时,您才可以在与上述相同的情况下运行。
对于任何生产设置,都应配置类似Kafka的功能以进行事件发布/使用。
答案 0 :(得分:0)
我了解这个lambda:
...
在事件成功持久后执行。如果 在执行此lambda之前,演员崩溃 成功发布事件,即之前 context.system.eventStream.publish(event)?
lambda在状态保持后运行。演员基本上会暂停自己的工作(将所有待处理的工作放在隐藏处),直到完成持久性,以便保持一致。
我是否正确理解在这种情况下该事件永远不会 会导致系统状态不一致?
否,由于上述原因,它将保持一致。
如果您的应用程序部署在一个JVM中,并且使用默认的Akka事件发布工具,那么JVM崩溃将意味着所有已发布但尚未处理的事件都将丢失,因为该工具没有任何恢复机制。
我想这取决于您默认事件发布的含义。常规演员,是的。如果您丢失了JVM,则将失去“常规”参与者。常规角色在内存中,就像普通的Java / Scala对象一样。坚持不懈的演员当然是另外一个故事。
您还说“已发布但尚未处理”。这些当然也丢失了。任何未“处理”的事物本质上都像是数据库尚未接收到的JDBC语句,或者消息未传输给Kafka等。该设计本质上是将事件立即保存到数据库中(几乎像交易日志),然后在已知可以安全保存之后进行工作。
如果您的应用程序部署在群集中,则只有在整个群集出现故障时,您才可以在与上述相同的情况下运行。
集群实际上只是为持久参与者提供了恢复的场所。群集仍依赖持久性存储进行恢复。
(我将答案集中在Akka永久演员上,答案随着诸如分布式数据之类的东西而变得更加多样化。)
对于任何生产设置,您都应配置诸如Kafka之类的功能以进行事件发布/使用。
不一定。持久模块绝对是一个一致的选择。 Kafka和Akka实际上只是具有不同目标的不同动物。 Kafka实际上是发布/订阅,Akka本质上采用了更多的事件源方法。我曾经使用过这两种系统,但是它们将它们用于不同的目的。