在此示例中,来自Akka持久文档
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)
成功持续了事件后执行。如果演员在成功发布事件之前执行此lambda时崩溃了,即在context.system.eventStream.publish(event)
之前?
我是否正确理解,在这种情况下,从未发布过这种事件,这可能会导致系统状态不一致?如果是这样,是否有任何方法可以检测到这种事情发生?
[编辑]
另外,如果您使用系统中发布的事件,请纠正我,如果我错了:
如果您的应用程序被部署在一个JVM中,并且您使用默认的Akka事件发布设施,则JVM崩溃将意味着由于该设施没有任何恢复机制,因此已发布但尚未处理的所有事件都将丢失。
如果将您的应用程序部署在集群中,则仅在整个群集下降时,您将在与上述相同的情况下运行。
对于任何生产设置
我知道这个lambda:
...
成功持续了事件后执行。如果什么 演员在执行此Lambda之前坠毁 事件的成功发布,即之前 context.system.eventstream.publish(event(?
lambda是在持续存在之后运行的。演员本质上暂停了自己(将所有未决的工作放在藏匿处(,直到持久性完整,以保持一致。
我正确理解的是,在这种情况下,事件永远不会 发布的可能导致系统状态不一致?
否,由于上述原因,它将保持一致。
如果您的应用程序部署在一个JVM中,并且您使用默认的Akka事件发布设施,则JVM Crash将意味着所有已发布但尚未处理的事件都将丢失,因为该设施没有任何恢复机制。
我想这取决于您默认情况下的含义。常规演员,是的。如果您失去JVM,您将失去"常规"演员。常规演员在记忆中,实际上就像普通的Java/Scala对象一样。持续的演员当然是另一个故事。
您还说"已发布但尚未处理"。当然,那些也丢失了。任何尚未"处理"的任何东西本质上都像尚未获得数据库的JDBC语句,或者尚未传输给Kafka的消息等。设计本质上是立即将事件保存到数据库的(几乎喜欢(事务日志(,然后在已知安全持续后进行工作。
如果您的应用程序部署在集群中,则只有在整个群集下降时,您将在与上述相同的情况下运行。
一个集群本质上只是为持久演员恢复的位置。集群仍然依靠持久商店进行恢复。
(我将这个答案集中在Akka持久的演员上,答案与分布式数据之类的东西变得更加不同。(
对于任何生产设置
不一定。持续模块绝对是一个一致的选择。Kafka和Akka实际上只是具有不同目标的不同动物。Kafka实际上是酒吧/sub,Akka实质上采用了更多的事件采购方法。我已经使用两者都使用的系统,但是它们用于非常不同的目的。