【发布时间】:2016-01-21 15:39:36
【问题描述】:
事件溯源和 CQRS 非常棒,因为它使开发人员摆脱了对一个预先建模的数据库的困扰,除非有大数据迁移项目,否则开发人员必须在应用程序的整个生命周期中使用该数据库。 CQRS 和 ES 还具有其他优势,例如扩展事件存储、审计日志等,这些优势已经遍布互联网。
但是有什么缺点呢?
以下是我在研究和编写小型演示应用程序后能想到的一些缺点
- 复杂:有人说 ES 很复杂。但我想说,拥有一个复杂的应用程序比一个复杂的数据库模型要好,在该模型上你只能使用查询语言(多个连接、索引等)运行非常受限的查询。我的意思是,像 Scala 这样的编程语言有非常丰富的集合库,可以非常灵活地生成一些非常复杂的聚合,还有 Apache Spark 可以轻松查询分布式集合。但是数据库总是受限于它的查询语言能力,并且分布式数据库比分布式应用程序代码更难(只需在另一台机器上部署另一个实例!)。
- 磁盘空间使用率高:事件存储最终可能会使用大量磁盘空间来存储事件。但是我们可以每隔几周安排一次清理并创建快照,也许我们可以将历史事件本地存储在外部 HD 上,以防我们将来需要旧事件?
- 高内存使用率:每个域对象的状态都存储在内存中,这可能会增加 RAM 使用率,并且我们都知道 RAM 是多么昂贵。 大问题!!因为我很穷!有什么解决办法吗?可以使用 Sqlite 而不是将状态存储在内存中吗?我是否通过在我的应用程序中引入多个 Sqlite 实例使事情变得更复杂?
- 启动时间较长:失败或软件升级启动速度较慢,具体取决于事件的数量。但是我们可以使用快照来解决这个问题吗?
- 最终一致性:某些应用程序存在问题。想象一下,如果 Facebook 使用 Event sourcing 和 CQRS 来存储帖子并考虑到 Facebook 系统的繁忙程度,如果我发布了帖子,我会在第二天看到我的 fb 帖子:)
- 事件存储中的序列化事件:事件将存储事件存储为序列化对象,这意味着我们无法查询事件存储中的事件内容,无论如何都不鼓励这样做。而且我们将来无法为该事件添加另一个属性。解决方案是将事件存储为 JSON 对象而不是序列化事件?但这是个好主意吗?或者添加更多事件来支持对原始事件对象的更改?
有人可以评论我在这里提出的缺点,如果我错了,请纠正我,并提出我可能错过的任何其他建议?
【问题讨论】:
-
为什么每个域对象的状态都存储在内存中?域对象在需要时从事件中重新创建。为什么你会认为 FB 不会使用事件溯源,只是因为他们很忙?我的理解是,他们使用一个写入主机和几个读取从机,它们“最终”同步,所以他们确实使用最终一致性,这就是为什么有时你可以发布一些东西,然后在你的提要中看不到它。
-
通常每个对象不会有数千个事件,但如果你这样做可能不会像你想象的那么慢(简单的选择没有连接来获取事件)然后应用到内存中。如果在性能测试中确实被证明是一个问题,您总是可以“快照”对象的事件。
-
事件溯源并不意味着最终的一致性。你可以做 ES 并立即保持一致。
-
您也可以立即与CQRS保持一致。
-
@cmr 看来您将许多不同的想法混为一谈。 Cqrs、事件溯源和最终一致性都是可以独立实现的不同想法
标签: cqrs event-sourcing