我认为事件溯源是CQRS的一种类型。它们之间的区别在哪里?什么使得事件溯源与其他类型的CQRS不同?
谢谢。
CQRS是由Greg Young引入的; 他在2010年的解释
CQRS只是在原本只有一个对象的情况下创建了两个对象。这种分离是基于方法是命令还是查询(与Meyer在命令和查询分离中使用的相同定义,命令是任何改变状态的方法,查询是任何返回值的方法)。
通常情况下,这意味着每个对象将使用不同的数据表示形式,以适应其目的。在这里,通常使用的术语是“写模型”和“读模型”。通常情况下,首先对写模型进行更改,然后异步传播到读模型。
事实上,“2”这个数字并没有什么神奇之处;你也可以有3个不同的表示形式,就像有两个一样。
这里的关键好处是您可以独立地调整数据结构以适应读取用例和写入用例。
让我们举一个简单的现实世界的例子:
CQRS: 我们将使用缓存/Redis/Elasticsearch来进行读取查询,使用数据库/MySQL/Mongo来进行写入查询。这就是CQRS的精髓。将读取和写入逻辑分离就是CQRS。
事件溯源: 所有我们使用的发布/订阅模式都属于事件溯源。在这里,我们将消息作为一个事件发布到队列(Kafka/RabbitMQ),而订阅者只需通过订阅这些队列来消费这些消息。
CQRS + 事件溯源: 让我们仍然使用上面的例子。 当任何更新到写入模型(数据库/MySQL/Mongo)中时,我们应该如何更新读取模型(缓存/Redis/Elasticsearch)呢?
我们可以在这里使用事件溯源。每当有任何更新到数据库中时,会创建一个包含更改内容的事件,并将该事件推送到队列中。现在,阅读器模型(Elasticsearch)将订阅这些队列并在其状态之上应用这些事件。因此,我们始终保持了读取和写入模型之间的相同状态。
CQRS代表命令查询职责分离。由Greg Young引入。每个方法都应该是执行操作的命令或返回数据的查询。命令不能返回数据,查询不能更改数据。每个模型都可以针对特定上下文进行优化,并保持其概念完整性。
事件溯源不是CQRS所必需的。您可以将事件溯源和CQRS结合使用。这种组合可能会带领我们走向一种新类型的CQRS。它涉及将应用程序所做的状态更改建模为不可变的事件序列或日志。您可能会想到系统日志和事件日志,但说实话,事件日志并不等同于事件溯源。事件溯源强制当前状态从历史中派生。如果您无法从历史推理出当前系统状态,则没有进行事件溯源。实际上,事件是业务事实。
在域驱动设计中,事件必须遵循普遍语言,系统中的所有事件必须在过去,并以过去时命名。事件是独立的,我是指事件应具有足够的数据来描述自己。
事件溯源越来越受欢迎。因为它使故障排除更容易,并且具有更好的性能特征;写入和读取可以独立扩展。GRASP事件溯源指的是松耦合的应用程序架构。此外,它还可以在未来添加需要处理相同事件但创建不同物化视图的更多应用程序。