5

嗨,我有以下塞纳里奥我不明白如何让最终一致性:域事件和版本没有CQRS

  1. 用户1使用基于任务的用户界面更改客户名称
  2. 应用服务调用操作上上客户名称骨料
  3. 骨料火灾事件改变
  4. 总线使用nservicebus
  5. NServicebus服务裸片发送消息
  6. 用户2得到聚集,并呼吁改变地址
  7. 聚合操作称为
  8. 域触发的事件
  9. 信息放在总线
  10. 客车重新启动
  11. 消息2拿起第一
  12. 消息2处理等有限上下文更新了新地址
  13. 消息1现在拿起这是错误的订单
  14. 现在会发生什么

如果我们在事件中传递聚合的版本,那么13中会有乐观的并发错误吗?

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

这是阻止我在我的域中应用事件的问题。所有帮助欢迎。

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

在命令处理程序和命令按下总线的意义上,我们不使用事件源或CQRS。只有我们想要异步发生的事件处理,因为我们有一个我们不希望改变的现有设计。

Blair

回答

3

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

+0

我不确定你的意思。我通过nservicebus发送活动,所以没有订购。如果我为我的事件添加序列号,我该如何在另一端执行排序?我错过了什么,一定有什么明显的我没有看到。 – 2013-03-02 12:17:15

+0

也有NServicebus与多个线程不保证他们将按顺序处理。 – 2013-03-02 12:19:59

+0

跟踪另一端的序列号。在序列号匹配'最后处理的序列号+ 1'之前不要处理该消息。 – 2013-03-02 12:21:09

0

哎呀:我刚才注意到你实际上是在你的榜样(客户名称,然后客户地址)使用2级不同的任务。当然,这不是问题,因为订单确实不重要。但我会留下我的回答,以防万一你的意图是有两个相同类型的变化。

一如往常几个问题/问题浮现在脑海中:

一件事你的例子并不需要一个端点失败,因为用户可以更新在同一时间的地址和处理的顺序可以是随机的。所以问题变成了哪一个是正确的地址。所以解决需要更多的分析。对于一两件事,我想我们可以假设一个客户不动非常频繁,2个用户在同一时间更新地址(甚至在它附近)--- :)

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

我认为要确定是否并发性,甚至一些其他的容忍这样的情况,是一个问题。所以也许地址只能每天更换一次,其他任何更改都需要其他互动。所以一些异常处理是一个选项。

你真的不应该走这归因于技术层面,试图解决它,而是看过程/业务的影响。

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

0

类似issuee与NServiceBus讨论here。 OP建议使用IBus.HandleCurrentMessageLater()旋转,直到其他消息到达。这可以工作,但可能会有问题,因为你永远不知道你需要等多久。

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

0

根据this你应该问自己:

什么是有故障对业务的影响?

在你目前的情况下,你有这个问题一次一百万个请求。如果您接受这两个请求都是有效的,我认为它不会对业务产生巨大影响。