DB事务和集成事件调度-如何使其原子化?

问题描述 投票:1回答:1

我正在设计一个具有多个有限上下文(微服务)的系统。我将有2种活动。

  • [Domain Events,发生在单个事务(同步)中的“内存中”]
  • Integration Events,在有界上下文之间使用(异步)

我的问题是,如何确保一旦提交事务(此时我确定所有Domain Events已成功处理),Integration Events也同样成功。

[当我提交事务时,通常我会分派Integration Events(例如,到队列),但是该队列也可能会关闭,因此以前“刚刚提交的事务必须被“还原”。怎么样?

我想到的唯一解决方案是将Integration Events存储到同一事务中的同一数据库中,然后处理Integration Events记录并将其推送到队列中-就像“使用当前数据库,作为前置队列,然后将其推入The Real Queue(但是我读到使用DB对此是反模式)。

是否有任何模式(可靠的方法)来确保:事务提交将消息推送到队列是原子操作?

编辑在阅读了https://devblogs.microsoft.com/cesardelatorre/domain-events-vs-integration-events-in-domain-driven-design-and-microservices-architectures/之后,作者实际上建议在同一数据库中使用“预先排队”的方法(他称其为“准备发布事件”)。

asynchronous queue microservices commit atomic
1个回答
0
投票

[结帐transactional outbox pattern

此模式确实会创建一个预队列。但最棒的是,将消息从预队列推送到真实队列是完全分离的。相反,您有一个称为“中间人”的消息中继,该消息中继读取您的事务日志并将事件从其推送到实际队列中。现在,由于发送消息和您的域事件已完全解耦,因此您可以在单个事务中处理所有域事件。

并且请确保您的所有服务都是一致的(即使有重复的呼叫,结果也一样)。此事务发件箱模式确实可以保证消息已发布,但是如果消息中继在发布后(确认之前)失败,则它将再次发布同一事件。

在其他情况下,全能服务也是必要的。由于事件总线(实际队列)可能有相同的问题。事件总线传播事件,服务确认,然后发生网络错误,然后由于未确认事件总线,因此将再次发送相同的事件。

嗯,实际上等幂可以解决整个问题。域事件计算完成(单个事务)后,如果发布消息失败,则服务可以简单地引发错误而无需回滚。由于未确认事件,因此事件总线将再次发送相同的事件。现在,由于该服务是幂等的,因此同一数据库事务将不会发生两次,它基本上将被覆盖或更好(应该)跳过并直接移至消息发布和确认。

© www.soinside.com 2019 - 2024. All rights reserved.