当演员状态只增加时,我可以使用akka持久性吗?

时间:2015-10-11 20:25:47

标签: event-sourcing akka-persistence

我正在尝试使用akka持久性来尝试实现一种服务,其中我的状态可能是非常大的(好吧,让它说它不适合RAM)一些实体的列表。让我们说用户希望所有实体的所有历史记录都可用。我可以在akka持久性中做到这一点吗?

现在我的演员状态看起来像那样。

case class System(var processes: Map[Long, Process] = Map()) {

  def updated(event: Event): System = event match {
    case ProcessDetectedEvent(time, activitySets, id, processType) =>
      val process = Process(activitySets.coordinates, time, activitySets.channels, id, processType, false)
      copy(processes = processes + (id -> process))

    case ProcessMovedEvent(id, activitySets, time) =>
      val process = Process(activitySets.coordinates, time, activitySets.channels, id, processes(id).processType, false)
      copy(processes = processes + (id -> process))

    case ProcessClosedEvent(time, id) =>
      val currentProcess = processes(id)
      val process = Process(currentProcess.coordinates, time, currentProcess.channels, id, currentProcess.processType, true)
      copy(processes = processes + (id -> process))
    case _ => this
  }

}

正如您所看到的,进程映射存储在内存中,因此如果进程数量很大,应用程序可能会耗尽内存。

3 个答案:

答案 0 :(得分:0)

有状态的actor使用Akka持久性来在actor启动,JVM崩溃后重新启动或者由主管迁移或在群集中迁移时恢复其内部状态。在这种情况下,从长远来看,应用程序/ JVM可能会因OutOfMemory异常而崩溃。当此actor重新启动时,持久性恢复机制将在地图中重新创建所有Process的信息。但是,总内存将会很高,应用程序可能会在运行时再次崩溃。因此,在这种情况下持久化对于避免应用程序崩溃没有帮助,除非您只保留部分进程列表以减少内存。

首先,您需要找到解决此内存异常的方法。也许你可以尝试以下选项。

  1. 尝试在OutOfMemory异常之后的JVM重新启动期间增加JVM堆大小。
  2. 在恢复状态时,仅重播选定的消息列表,以便使用的总内存较少但状态不完整。
  3. 如果恢复期间要重播的邮件列表太大,可以使用快照来缩短状态恢复时间。

答案 1 :(得分:0)

也许您想要考虑是否有有意义的方法将数据集划分为具有合理范围的范围。然后,您可以通过持久化actor表示每个范围,如果您需要跨越整个商店的信息,则必须使用某种协调器来管理范围并对其进行迭代。但是根据它开始变得多么复杂,在某些时候,我不得不怀疑你是否要重新发明map-reduce或Spark。

答案 2 :(得分:-1)

我认为您可能正在寻找的东西(至少它是另一种选择)是快照。

使用事件源和事件回复时,通常建议的方法是经常使用快照。

因此,当您返回事件时,您将获得快照,然后返回自该快照以来发生的事件。这意味着您从事件存储流中传输的对象较少(内存较少),处理和应用的事物较少(更快)...但这确实伴随着它自己的权衡......我赢了#39在这里讨论。

这再次只涉及最常见的情况。如果您的事件处理发生了变化,那么您可能需要重建您的活动......虽然这会引发一些关于您如何构建系统的相当严肃和有趣的问题。

我看起来并不太紧密,但是akka可能有这种内置快照的概念。如果没有,那么在前面的道路上会有一个学习曲线和大量的反复试验,因为你开始按照理想的方法开出所有那些没有走过的道路,但现实世界会向你投掷。