5

嗨,我有以下 senario,我不明白如何获得最终的一致性:

  1. 用户 1 使用基于任务的 ui 更改客户名称
  2. 应用服务调用聚合上的操作
  3. 客户名称上的聚合触发事件已更改
  4. 总线使用 nservicebus 发送消息
  5. NServicebus 服务终止
  6. 用户 2 获得聚合并调用更改地址
  7. 聚合操作称为
  8. 触发域事件
  9. 信息放在公共汽车上
  10. 巴士重新启动
  11. 消息 2 最先收到
  12. 消息 2 已处理,其他有界上下文已更新为新地址
  13. 现在收到消息 1,这是错误的顺序
  14. 现在会发生什么

在 13 中如果我们在事件中传递聚合的版本会不会出现乐观并发错误?

如果是这样,消息 1 new 将应用于其他上下文中的对象。我们如何保持一致性?

这是阻止我在我的域中应用事件的问题。欢迎大家帮忙。

基本思想是在另一个上下文中更新另一个聚合。我只是停留在这个并发技术上。

我们没有在命令处理程序和总线上推送命令的意义上使用事件源或 CQRS。这只是我们希望异步发生的事件处理,因为我们有一个我们不希望更改的现有设计。

布莱尔

4

4 回答 4

3

通常你会排队的消息。如果他们要排队,您将获得正确的排序。如果您想使用不支持通过您的服务总线排序的东西,请为您的事件添加一个序列号,以便另一方可以正确地重新排序它们。TCP 自 1981 年以来一直在这样做http://www.ietf.org/rfc/rfc793.txt :)

于 2013-03-02T12:08:12.297 回答
0

这里讨论了与 NServiceBus 类似的问题。OP 建议使用 IBus.HandleCurrentMessageLater() 旋转直到另一条消息到达。这可以工作,但可能会出现问题,因为您永远不知道要等待多长时间。

一个更复杂的选择是使用saga这将等到导致特定版本的所有消息都到达。在这种情况下,排序是基于版本完成的,并且只有在聚合版本中的所有更改都发布到另一个 BC 时才有可能。假设消息 1 在聚合的版本 2 上运行。然后它增加聚合的版本并发布一个事件,说明它已在版本 2 上运行。消息 2 在聚合的版本 3 上运行并发布一个事件,说明它已在版本 3 上运行。当另一个 BC 中的 NServiceBus 端点在消息 1 之前收到消息 2,它知道最后收到的消息是在聚合的版本 1 上操作的,所以它需要一个在版本 2 上操作过的消息。它将启动一个等待下一条消息的 saga。一旦它收到消息 1,saga 将应用消息 1,然后应用消息 2 并释放 saga 状态。如果使用版本进行测序是不可接受的,则可以使用另一种测序策略。

于 2013-03-02T18:10:18.110 回答
0

糟糕:我刚刚注意到您在示例中实际上使用了 2 个不同的任务(客户名称,然后是客户地址)。当然,这不是问题,因为顺序真的不重要。但我会留下我的答案,以防万一您的意图是进行两个相同类型的更改。

与往常一样,我会想到几个问题/问题:

一方面,您的示例不需要端点失败,因为 2 个用户可以同时更新地址,并且处理的顺序可以是随机的。所以问题变成了哪一个是正确的地址。所以解决这个问题需要更多的分析。一方面,我想我们可以假设一个客户不会如此频繁地移动,以至于 2 个用户同时更新地址(甚至在它附近)--- :)

即便如此,也许第一个地址是正确的。

我认为对于这种情况,您想确定并发性,甚至是其他一些容忍度是否是一个问题。因此,也许一个地址每天只能更改一次,而任何其他更改都需要其他一些交互。因此,一些异常处理将是一种选择。

您真的不应该将其降低到技术级别来尝试解决它,而是查看流程/业务影响。

对于一个简单的解决方案,我会将消息发送日期与特定类型的最后操作日期匹配。因此,ChangeAddressCommand在处理消息时,您可以与当前消息进行比较LastAddressChange,如果消息是在上次更改日期之前发送的,则拒绝它。

于 2013-03-02T17:45:57.943 回答
0

据此,应该问自己:

失败对业务的影响是什么?

在您当前的情况下,一百万个请求您会遇到此问题。如果您接受这两个请求为有效,我认为这不会对业务产生巨大影响。

于 2014-05-24T10:13:25.580 回答