如何管理DDD中域逻辑与事件之间的交易? [英] How manage transaction between domain logic and events in DDD?

查看:139
本文介绍了如何管理DDD中域逻辑与事件之间的交易?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究DDD和事件源中的编程。



我看到一个例子,当一个域逻辑被调用(例如 Order .placeOrder())它会发布一个事件(例如 OrderPlaced )。事件将作为事件存储发送到MQ。



域逻辑( Order.placeOrder() )应该是一个原子API,如果使用Spring作为事务管理器,它应该有 @Transactional 注释。



现在我的问题是:


  1. 如何确保DB更改和事件发送在同一个事务中?即如果将数据提交到DB中有任何错误,事件不应发送到MQ。



    我知道有一些解决方案,如XA或2阶段提交强制DB在同一事务中更新和发送MQ消息。但是似乎现在没有被广泛使用。


  2. 如果仍然使用Spring @Transactional 注释,而没有XA在事务提交成功后,我们可能会做一些逻辑吗?最好的做法是什么?



解决方案

必须拥有一个可靠的系统:




  • P1:已发布的域事件必须描述一个真正发生的变化(即确保没有鬼事件开始飞行)。

  • P2:触发域事件的数据库更改必须导致正在发布的事件(即不要丢失事件)。



有以下几种可能性来实现,所有这些都使用过我自己或被看到在一个项目中使用:


  1. 使用消息传递基础设施,使用与您的应用程序相同的数据库,以便可以使用单个事务。这个解决方案是可行的,当一个非常简单的消息传递基础设施就足够了,团队决定自己建立它。


  2. 使用两个阶段的提交。我不会有这样的印象,这不再被使用,但也许没有多少谈论,因为它不是奇特的技术...


  3. 使用一些聪明的欺骗,以确保两个条件。例如。用我所说的鸡蛋解决方案:




    • 首先同步发布事件,然后持续到DB。这确保P2保持。

    • 然后使用检查事件流的事件处理器,并检查是否在数据库中找到事件。如果没有,请从流中删除事件。这确保P1保持。


解决方案3需要仔细设计和审查保证系统的每个部分都根据故障行为,所以它可能是最难的一个正确的。但它也是一个非常优雅的解决方案,一旦它的工作。



顺便说一下,我不同意,Spring注释应该添加到域对象,而是各自的应用服务。这只是一个旁注。


I am studying on the programming in DDD and event source.

I saw one example that when a domain logic was called (e.g. Order.placeOrder()) it would publish an event (e.g. OrderPlaced). And the event would be sent to MQ as the event store.

The domain logic (Order.placeOrder()) should be an atomic API, and it should have @Transactional annotation if using Spring for the transaction manager.

And now my question is:

  1. How to make sure the DB change and event sending are within the same transaction? i.e. If there any error when committing data into DB, the event should never send to MQ.

    I know that there is solution like XA or 2 phase commit to force the DB update and sending MQ messages within the same transaction. But seems it is not widely used nowadays.

  2. If still using Spring @Transactional annotation and no XA, is it possible that we do some logic after the transaction is committed successfully? What is the best practice to do that?

解决方案

The following two properties must hold to have a reliable system:

  • P1: Published domain events MUST describe a change that really happened (i.e. make sure no ghost events start flying around).
  • P2: Changes to the DB that trigger domain events MUST result in an event being published (i.e. don't lose events).

There are the following possibilities to achieve this, all of which I've either used myself or seen being used in a project:

  1. Use a messaging infrastructure that uses the same database as your application, so that a single transaction can be used. This solution is viable when a very simple messaging infrastructure suffices, and the team decides to build it themselves.

  2. Use 2 phase commits. I don't have the impression that this is not used anymore, but maybe it's less talked about, because it isn't fancy technology...

  3. Use some clever trickery to ensure both conditions hold. E.g. with what I call the chicken and egg solution:

    • Always publish events synchronously first, then persist to the DB. This ensures P2 holds.
    • Then use an event processor that inspects the event stream and checks whether an event can be found in the DB. If not, remove the event from the stream. This ensures P1 holds.

Solution 3 requires careful design and review of the guarantees each part of the system makes in terms of failure behavior, so it is probably the most difficult one to get right. But it is also a very elegant solution, once it works.

By the way, I don't agree that Spring annotations should be added to domain objects, but rather to the respective app services. This only as a side note.

这篇关于如何管理DDD中域逻辑与事件之间的交易?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆