【问题标题】:Event-sourcing: when (and not) should I use Message Queue?事件溯源:我应该何时(而不是)使用消息队列?
【发布时间】:2017-04-29 03:13:34
【问题描述】:

我正在使用 Java 和 Cassandra 的事件源从头开始构建一个项目。 我的应用程序基于微服务,在某些用例中信息将被异步处理。我想知道消息队列(例如 Rabbit、Active MQ Artemis、Kafka 等)将发挥什么作用来改进这种环境中的技术堆栈,以及如果我不使用它是否了解这些场景。

【问题讨论】:

    标签: asynchronous message-queue event-sourcing


    【解决方案1】:

    确保您清楚发送(命令)和发布(事件)之间的区别。 Udi Dahan 在他的 busses and brokers 文章中谈到了这个话题。

    在您进行事件溯源的大多数情况下,您确实希望从已发布的事件中重建状态。如果您需要状态,则查询历史的技术权威/记录簿,并从历史中重建状态。

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

    在某些情况下,您可能会同时使用这两种方法。例如,如果您正在更新缓存视图,您将订阅各种BobChanged 事件以了解您的缓存数据何时过时;要重建陈旧的视图,您需要重新加载历史的表示并将其转换为更新的视图。

    【讨论】:

      【解决方案2】:

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

      但它们不会无限期地存储所有消息。您需要有一个事件存储来执行任何类型的事件采购。

      问题不是“排队还是不排队”,而更像是:

      • 这东西可以无限存储大量的事件吗?
      • 它有发布-订阅功能吗?
      • 它是否提供至少一次交付保证?

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

      【讨论】:

        【解决方案3】:

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

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

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

        如果您查看事件是如何持久化的,您会发现它们作为一个事务保存到存储中。如果您随后需要发布事件,这将是另一个事务。由于您要处理两个不同的基础架构,因此可能会出现问题。

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

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

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

        【讨论】:

        • 谢谢 Alexey,这里有一个快速的问题:“排序和重复问题,不管是谁,都不适用于像 Kafka 这样的事件流服务器”?如果您有并发订阅者,如果这些并发订阅者相互依赖,则不可避免地会出现乱序问题,因此应该根据特定应用程序的业务规则在它们之间实现一些自定义同步。我的理解正确吗?
        • 我个人对 Kafka 没有经验,但我在 DDDU 2016 dddeurope.com/2016/martin-kleppmann.html 上观看了 Martin Kleppmann 的谈话,他解释说,当他们设计 Kafka 时,他们的目标是严格的事件排序。我也知道 EventStore 在使用追赶/追赶订阅时保证事件顺序。当您在事件流上设置竞争消费者时,这种保证不可避免地会失效,您无法在那里保证订购。异步处理也会破坏排序。
        • 我明白了。我之所以这么问是因为在任何 HA 系统中,您都必须有相互竞争的消费者才能获得容错能力,而且看起来没有机制可以自动处理此类系统的无序情况。
        • @IlliakaillI 是的,我相信对于竞争消费者而言,通用排序在理论上是不可能的,并且必须由系统使用传入消息和进程内通信的某些属性来处理。
        猜你喜欢
        • 2019-09-18
        • 2014-02-13
        • 2011-06-30
        • 2017-11-12
        • 2011-05-14
        • 2021-02-04
        • 1970-01-01
        • 2020-07-12
        • 2018-09-18
        相关资源
        最近更新 更多