我要描述的内容实际上是两个不同系统之间的两阶段提交问题,我正在寻找有关如何处理它的建议。在我们的Web应用程序中,我们将一些昂贵的/第三方操作(例如发送电子邮件)卸载到带外后台工作进程(我们将其称为我们的作业基础结构。)
例如,要发送电子邮件,我们会在数据库中创建电子邮件对象和电子邮件作业。然后,我们必须等待我们的工作监视器获取电子邮件作业并发送它。作业监视器基本上通过在空闲时每隔几秒轮询一次数据库来工作。
然而,这会增加电子邮件发送的延迟,并添加我在数据库中通过轮询查看的过度负载。如果我们能够在创建电子邮件后立即将电子邮件作业放在队列中,那就更好了。
然而,这目前失败有两个原因。首先,队列通常比Web请求快得多。在Web请求提交其数据库事务之前,将拾取电子邮件以进行处理,因此无法正确生成电子邮件。其次,如果Web请求失败,它将回滚其数据库事务,这意味着电子邮件应不发送。但是,如果它已经被放入队列中,那么它就不再受请求的控制。
在队列和数据库之间创建两阶段提交是否有好的策略?作为参考,我们使用RabbitMQ和MySQL与InnoDB表。我提出的一个想法是在提交数据库事务后将电子邮件作业粘贴到队列中,但这样就可能使电子邮件永远不会排队。我仍然需要创建一个轮询流程来监视应该已发送但未发送的电子邮件。
答案 0 :(得分:0)
我意识到这已经晚了几年:)但是我想对其他遇到这个问题的人提出一些想法。
您可以延迟发送消息,以增加数据库在作业获得时就绪的可能性。我从未使用过RabbitMQ,但我发现这个使用rabbitMQ队列作为延迟队列How to create a delayed queue in RabbitMQ?的例子。您的电子邮件作业仍然需要处理任何未注释的记录,因为延迟不是处理分布式处理的确定性方法。
尽管如此,感觉还有改进设计的空间。通常,对于服务体系结构,在服务之间共享数据库表是个坏主意。它导致分布式事务和扩展问题。我会尝试确保RabbitMQ消息包含独立于任何其他服务处理电子邮件所需的所有数据。或者,如果它需要更多数据,它应该通过ServiceBus请求而不是数据库查询来请求数据。