没有 CQRS 的事件溯源

Event sourcing without CQRS

我知道 CQRS 可以在有或没有 event sourcing 的情况下实施,但它在另一端是否有效?没有 CQRSevent sourcing 有意义吗?如果可以,应该如何实施?

Does event sourcing without CQRS make sense?

是的,从某种意义上说,CQRS 和事件溯源是正交问题。

这就是它在罐头上所说的 - 你有一个管理历史的模型,既应用更新到该历史以响应命令,又从该历史构建对查询的响应。

class BankAccount {
    final History<Transactions> transactions;

    void deposit(Money money) {...}
    Money computeInterestAccruedSince(Date lastReview) { ... }

}

是的,确实如此。

基本上,事件溯源的整个思想只是存储导致当前状态的更改,而不是存储当前状态。这样,通过事件溯源,您会自动拥有历史记录,并且可以 运行 对数据进行时间序列分析,并尝试从过去吸取教训。

是否使用 CQRS 则完全不同:CQRS 是关于将写入应用程序与读取应用程序分开。

就像您可以在没有事件溯源的情况下使用 CQRS 一样,您可以在没有 CQRS 的情况下使用事件溯源。两者都是相互独立的,只是一不小心就很契合。

我还没有看到您在不使用 CQRS 的情况下使用 ES 的情况,因为只有当您不需要跨越 1 个以上实体的任何 query/analyses 功能时才会出现这种情况。 99% 的情况下这是一项要求 ;)

如果你想查询多个实体,你肯定需要像 CQRS 这样的东西,因为你将应用一种不同的方式来查询你的数据,而不是使用事件源。 (除非您想在每次查询时重播所有事件。)不过,您如何着手实施 CQRS 部分并不是一成不变的。它只是描述了阅读和写作是两个以不同方式处理的独立问题。

总的来说:不,这没有任何意义。

CQRS 是关于将读取与写入分开的。写操作需要诸如锁定、保证顺序和始终最新状态之类的东西。在经典系统(关系数据库)中,您还会为读取操作提供这种保证,这会带来巨大的性能影响和可伸缩性方面的大问题。这就是为什么在 CQRS 中,您为读取操作提供一个单独的数据副本,该副本针对快速读取进行了优化,例如它被非规范化并放入更高效、更快的系统(例如内存缓存)中,我称之为 "read view [on the system's data]".

CQRS 无需 ES 即可工作,因为您可以从传统数据存储(例如关系数据库)创建优化的读取视图。

ES 在没有 CQRS 的情况下也能正常工作,但前提是事件数量相当小。因为您将系统的所有更改存储在数据库中,并且每次读取都必须使用相同的数据库并遍历完成查询所需的所有事件。最终需要阅读的事件太多才能回答,回答的时间就会变得太长。