【问题标题】:NServiceBus and concurrencyNServiceBus 和并发
【发布时间】:2015-05-28 23:51:23
【问题描述】:

此链接讨论了NServiceBus 如何处理 sagas 的并发性。但是,它没有显示解释何时会发生并发的示例。在电子商务应用程序中,订单是每个用户的,因此不会出现多个用户更新同一订单的情况。我没有看到订单系统和运输系统更新同一订单的案例(订单传奇)。它们发生在不同的时间。

除非开发人员编写代码来同时更新多个代理的同一订单,否则是否会出现并发问题?

【问题讨论】:

    标签: concurrency nservicebus


    【解决方案1】:

    可能存在脏写的并发示例

    一个简单的并发示例是当您有订单项时。每个项目都由单独的消息添加。

    它们共享相同的订单 ID。假设这些消息并行处理,现在可能会出现并发问题,因为两者都希望扩展订单 saga,因此其中一个必须失败并重试,否则我们将有脏写。

    无限线程/工作者

    查看是否可能存在潜在并发问题的另一种方法是想象有无限线程能够处理您完整的积压消息,并考虑这是否会导致多条消息想要创建、更新或删除一个 saga 实例和如果这会导致问题。

    幂等性和多次传递

    在多次接收同一消息时也会出现并发问题。这需要去重或其他形式的幂等处理。并非所有队列传输都提供“仅一次交付”,因为其中许多不是事务性的或配置为具有高可用性。

    事件排序

    这是一个很好的假设,即使事件本质上是按时间顺序排列的,因为您无法控制其他端点何时能够处理消息。

    只有当 saga 实例控制特定的工作流程时,您才能依赖它。

    【讨论】:

      【解决方案2】:

      了解什么样的场景并发检查相关的关键:

      如果您的端点使用多个工作线程运行,则有可能 多条消息将同时命中同一个 saga 实例。

      假设您有多个线程处理相同的传入消息,这在设计为高性能的系统中并不罕见。为了便于讨论,假设我们有一个名为“OrderAccepted”的事件,它是订单从创建到履行的触发器。

      如果您有多个线程处理该事件,并且相应的 saga 应该从头到尾按照此顺序,您只希望一个线程实际连接所述 saga 并开始处理。否则,您可能会遇到两次分配股票、两次付款的情况……

      所以回答你的问题:当然允许不同的进程对不同的消息采取行动,一个进程可以实例化一个 saga 来创建订单,另一个进程可以实例化一个 saga 来在处理不同的消息时标记一个发货订单,等等

      saga 并发检查试图解决的问题是竞争条件,即两个(甚至更多)进程都试图以相同的方式处理消息,这可能导致采取重复的操作。

      为了说明他们如何做到这一点,让我们给一个 saga 一个修订(或版本)号。

      1. 一条消息被放到总线上,名为“CreateOrder”,orderID 为“1”
      2. 进程 A 和 B 都尝试处理消息
      3. 进程 A 实例化一个新的 saga,其修订版为 1
      4. 进程 B 几乎同时实例化一个新的 saga,它的修订版也为 1
      5. 进程 A 的 saga 处理消息,并且该 saga 已提交修订版 1 6/ 进程 B 的 saga 处理消息,尝试提交,注意到它的修订不匹配,因为修订 1 已经提交。然后它回滚它的动作。一级重试(可能还有二级重试)开始。
      6. 作为重试的一部分,进程 B 尝试再次处理消息,加载现有的 saga,启动 idem-potency 检查,进程 B 注意到消息已被处理并且什么也不做。

      【讨论】:

      • 在第 2 步中,您提到了进程 A 和 B。您的意思是两个“节点”吗?如果只有一个节点,不会只有一个进程或应用程序边界,因此没有机会产生多个线程来处理相同的 CreateOrder 消息?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多