事件溯源:何时(以及不)应该使用消息队列?

问题描述 投票:0回答:3

我正在使用 Java 和 Cassandra 进行事件溯源从头开始构建一个项目。

我的应用程序基于微服务,在某些用例中信息将被异步处理。我想知道消息队列(例如 RabbitMQ、ActiveMQ Artemis、Kafka 等)在这种环境下将发挥什么作用来改进技术堆栈,如果我不使用它,我是否了解场景。

asynchronous message-queue event-sourcing
3个回答
33
投票

我首先将像 RabbitMQ 这样的消息基础设施与像 Kafka 这样的事件流/存储/处理分开。这是为两个(或更多)不同目的而制作的两种不同的东西。

关于事件源,你必须有一个必须存储事件的地方。该存储必须是仅附加的,并支持基于身份的非结构化数据的快速读取。这种持久性的一个例子是EventStore

事件溯源与 CQRS 结合在一起,这意味着您必须将更改(事件)投影到另一个可以查询的商店。这是通过将事件投影到该存储来完成的,这是处理事件以更改域对象状态的地方。重要的是要理解,使用消息基础设施进行预测通常是一个坏主意。这是由于消息传递的性质和两阶段提交问题造成的。

如果您查看事件如何持久化,您可以看到它们作为一笔事务保存到存储中。如果您随后需要发布事件,这将是另一笔交易。由于您正在处理两个不同的基础设施,因此事情可能会被破坏。

这样的消息传递问题是,通常保证消息“至少传递一次”,并且通常不保证消息的顺序。此外,当您的消息使用者失败并且 NACK 消息时,消息将被重新传递,但通常会晚一点,再次破坏序列。

无论是谁,排序和重复问题都不适用于像 Kafka 这样的事件流服务器。此外,如果您使用追赶订阅,EventStore 将保证仅按顺序交付一次事件。

根据我的经验,消息用于发送命令并实现事件驱动架构,以反应方式连接独立服务。另一方面,事件存储用于持久化事件,只有到达那里的事件才会被投影到查询存储并发布到消息总线。


7
投票

确保您清楚发送(命令)和发布(事件)之间的区别。 Udi Dahan 在他关于“巴士和经纪人”的文章中谈到了这个话题。 在大多数情况下,当您进行事件溯源时,您“不”希望从已发布的事件重建状态。如果您需要状态,请查询技术权威/记录簿以获取历史记录,并从历史记录中重建状态。

另一方面,消息队列中的事件驱动活动应该没问题。当单个事件(加上订阅者的状态)拥有您需要的一切时,那么离开总线就可以了。

在某些情况下,您可能会两者都做。例如,如果您要更新缓存视图,您可以订阅各种 BobChanged 事件来了解缓存数据何时过时;要重建陈旧的视图,您需要重新加载历史记录并将其转换为更新的视图。

在事件源应用程序的世界中,消息队列通常允许您在生产者和消费者之间实现发布-订阅模式风格的通信。此外,它们通常会帮助您提供传递保证:哪些消息已传递给哪些订阅者,哪些消息没有传递给哪些订阅者。


6
投票

问题不是‘排队还是不排队’,而更像是:

这个东西可以无限期地存储大量事件吗?

它有发布订阅功能吗?
  • 是否提供至少一次交付保证?
  • 因此,您应该使用像
  • Kafka
EventStore

这样的东西来开箱即用。或者,您可以手动将事件存储与消息队列结合起来,但这会涉及更多。

© www.soinside.com 2019 - 2024. All rights reserved.