【问题标题】:How manage transaction between domain logic and events in DDD?如何在 DDD 中管理域逻辑和事件之间的事务?
【发布时间】:2015-10-14 06:14:51
【问题描述】:

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

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

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

现在我的问题是:

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

    我知道有像 XA 或 2 阶段提交这样的解决方案来强制数据库更新和在同一事务中发送 MQ 消息。但现在似乎没有被广泛使用。

  2. 如果仍然使用Spring @Transactional注解并且没有XA,是不是我们在事务提交成功后做一些逻辑呢?这样做的最佳做法是什么?

【问题讨论】:

    标签: java spring transactions event-handling domain-driven-design


    【解决方案1】:

    要拥有可靠的系统,必须具备以下两个属性:

    • P1:已发布的域事件必须描述真正发生的变化(即确保没有鬼事件开始四处飞舞)。
    • P2:对触发域事件的数据库的更改必须导致事件被发布(即不要丢失事件)。

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

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

    2. 使用 2 阶段提交。我没有这个不再使用的印象,但可能它很少被谈论,因为它不是花哨的技术......

    3. 使用一些巧妙的技巧来确保这两个条件都成立。例如。用我所说的鸡和蛋的解决方案:

      • 始终先同步发布事件,然后持久化到数据库。这确保了 P2 成立。
      • 然后使用事件处理器检查事件流并检查是否可以在 DB 中找到事件。如果没有,请从流中删除该事件。这可确保 P1 成立。

    解决方案 3 需要仔细设计和审查系统每个部分在故障行为方面所做的保证,因此它可能是最难做到的。但它也是一个非常优雅的解决方案,一旦它起作用。

    顺便说一句,我不同意应将 Spring 注释添加到域对象中,而是应添加到相应的应用程序服务中。这只是一个旁注。

    【讨论】:

    • 感谢您的回复。使用与事件相同的数据库确实是一种简单的事务管理方法。我认为这对内部事件有好处。但是,如果我们需要发布外部事件以供大量订阅者使用。办案的做法是什么?我们是否需要额外的调度程序来将事件从 DB 事件存储转移到 MQ 等 ESB 产品?
    • @RandyHuang 这取决于您的环境。您可以使用调度程序或在原始事务结束时触发“检查新域事件”。
    猜你喜欢
    • 1970-01-01
    • 2019-08-23
    • 2013-05-19
    • 1970-01-01
    • 2016-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多