事件溯源模式:为什么我不能存储当前状态?

Event sourcing pattern: why mustn't I store current state?

我正在学习事件溯源模式,但我有一点不明白。

在很多教程中都有将实体的当前状态存储在数据库中的说明。开发人员应该构建一个基础设施,用于从与所需实体相关的数据库中提取所有事件 ("event stream"),然后将它们应用于新的所需类型对象,因此最终是当前状态。

让它成为一个银行账户。要 return 向我的客户报告她当前的帐户状态,我必须:

  1. 提取所有相关事件(数据库中可能有数千个事件)
  2. 计算当时的免费金额。

但是性能呢?我认为最好只存储每个帐户的当前状态,并且新事件会立即对其产生副作用。我说的不对吗?

事件溯源的重点是保持状态为一系列变化,因此拥有当前状态与 ES 是相反的。

也就是说,由于性能要求,有时 snapshot is created so that updates are not applied from the beginning, but only from the snapshot forward. Event stores are specialized databases targeted at applications using event sourcing and they can provide the snapshot functionality out of the box

等式的另一部分是 ES 与 CQRS - Command Query Responsibility Segregation pattern which separates read and write models (previous link didn't get it quite right, IMO, you might want to look at this one) 互补。然后正在执行的命令或领域事件用于不断更新读取模型,它实际上是当前状态的非规范化表示。因此,对于命令,您将从事件 (ES) 构建域对象并对其执行操作,而对于查询,您将绕过事件存储并直接从读取模型中检索数据,该模型可以是关系数据库、文档数据库或其他经过优化的模型适合您的阅读场景。

如果您有 mostly-reading 个应用程序,那么使用 ES 实现的命令端的性能可能并不那么关键。

ES 的好处超出了这个问题的范围,您可以在互联网上找到很多信息(尤其是 Greg Young 和 Udi Dahan)。我个人对此有点怀疑,并且发现如果处理较长的 运行 业务场景,它是有意义的。