【问题标题】:Implementing sagas with Kafka用 Kafka 实现 sagas
【发布时间】:2021-04-06 23:07:12
【问题描述】:

我正在使用 Kafka 进行事件溯源,并且我对使用 Kafka 实现 sagas 很感兴趣。

关于如何做到这一点的任何最佳做法?提到的指挥官模式here 似乎接近我正在尝试构建的架构,但演示文稿中的任何地方都没有提到 sagas。

【问题讨论】:

    标签: apache-kafka event-sourcing saga


    【解决方案1】:

    今年 DDD eXchange 的这次演讲是我在事件驱动/CQRS 系统中遇到的流程管理器/Saga 模式的最佳资源: https://skillsmatter.com/skillscasts/9853-long-running-processes-in-ddd (需要注册免费账号才能查看)

    那里显示的演示位于 github 上:https://github.com/flowing/flowing-retail

    我试了一下,我很喜欢。我确实建议先观看视频以做好准备。

    虽然显示的方法与消息总线无关,但该演示使用 Kafka 作为流程管理器来向其他有界上下文发送命令并侦听事件。它不使用 Kafka Streams,但我不明白为什么它不能插入到 Kafka Streams 拓扑中并成为更广泛架构的一部分,就像您引用的 Commander 演示文稿中描述的那样。

    我希望根据我们自己的需要对此进行进一步调查,因此请随时在 Kafka 用户邮件列表上发起一个线程,这是就此类模式进行协作的好地方。

    希望有所帮助:-)

    【讨论】:

      【解决方案2】:

      我想在这里添加一些关于 sagas 和 Kafka 的内容。

      一般


      总的来说,Kafka 与普通队列略有不同。它在缩放方面特别好。这实际上会导致一些并发症。

      实现扩展的方法之一,Kafka 使用数据流的分区。数据放置在分区中,可以按照自己的速率使用,独立于同一主题的其他分区。以下是有关它的一些信息:how-choose-number-topics-partitions-kafka-cluster。我会回来解释为什么这很重要。

      在 Kafka 中确保顺序的最常用方法是:

      • 为主题使用 1 个分区
      • 使用分区消息键将消息“分配”给主题

      在这两种情况下,您按时间顺序排列的消息都需要流经同一主题。

      另外,正如@pranjal thakur 指出的那样,请确保将传递方式设置为“恰好一次”,这会影响性能,但可以确保您不会多次收到消息。

      警告


      现在,需要注意的是:更改分区数量时,分区上的消息分布(使用密钥时)也会更改。

      在正常情况下,这很容易处理。但是,如果您遇到高流量情况,则向不同数量的分区迁移可能会导致在某个时刻在多个分区上处理 saga-“流”,并且此时无法保证顺序。

      这是否会成为您的方案中的问题取决于您。

      您可以提出以下问题来确定这是否适用于您的系统:

      • 如果您需要使用 Kafka 将数据迁移/复制到新系统,会发生什么情况?
        (高流量场景)
      • 您可以将数据发送到 1 个主题吗?
      • saga 服务暂时中断后会发生什么?
        (低可用性场景/高流量场景)
      • 当您需要重播一堆消息时会发生什么?
        (高流量场景)
      • 如果我们需要增加分区会发生什么?
        (高流量场景/中断和恢复场景)

      另一种选择


      如果您正在考虑根据步骤(例如状态机)设置 saga,我会要求您重新考虑一下您的设计。

      我举个例子:

      让我们考虑一个预订酒店房间的流程:

      简单来说,它可能包含以下步骤:

      • 预留处理室(传入事件)
      • 处理房间已付款(传入事件)
      • 发送预订确认(在付款和一些处理之后)

      现在,如果您的 saga 无法在预订尚未到来的情况下处理付款,那么您将依赖于事件的顺序。

      在这种情况下,您应该问自己:什么时候会中断?


      如果你断定你想避免时间依赖;考虑一个没有 saga 的系统,或者一个不依赖于事件顺序的 saga - 即:接受所有消息,即使过程中还没有轮到他们。

      一些例子:

      • 聚合器
      • 建模为业务流程:并行网关(并行流程)

      请注意,在这样的设置中,每个动作都有一个已实施的补偿动作(回滚动作),这一点更为重要。

      我知道这通常很难实现;但是,如果你从小处着手,你可能会开始喜欢它:-)

      【讨论】:

      • 我不熟悉 Kafka,但我认为该示例在我使用过的系统中无效。您将拥有一个保留 saga 状态的数据存储。当引发相关事件时,您的 saga 将作为响应被触发,然后检查您的数据存储的当前状态。它最终会在适当的时候触发。
      • 这是可能的,并且可能您的系统设计得很好。我要说的是,if 您的逻辑依赖于状态机,该状态机取决于验证转换到不同状态的事件顺序,那么,在使用 Kafka 时,您会遇到一些严重的问题
      • 如果消息进入同一个分区,Kafka 会以正确的顺序传递消息,并且所有具有相同 key 的消息都会进入同一个分区。这样,如果您使用相同的密钥(我不确定这是否是一种普遍做法,但我们总是有一个相关 id 用于在我们的 sagas 中进行跟踪),您的消息应该以正确的顺序传递给特定事务。我明白你的意思,在没有很好理解的情况下粗心地使用 Kafka 可能会导致问题,但是如果你已经在使用 kafka 和 kafka-streams,那么考虑其他队列将会做更多的工作。
      • @Stefan 现在看起来好多了:) 我还想补充一点在 Saga 中使用 Kafka 的挑战,即我们应该将 Kafka 配置为“恰好一次”处理消息(默认配置为卡夫卡正在处理“至少一次”的消息)。在我们的系统中,它已经以这种方式配置,这会稍微降低性能,但如果您的系统没有以这种方式配置,您需要决定性能下降是否真的值得。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-13
      • 2020-04-24
      • 2021-09-09
      • 2017-11-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多