与数据库和消息队列记录的最终一致性

ayo*_*age 10 database domain-driven-design message-queue eventual-consistency microservices

我有一个应用程序,我需要将一些数据存储在数据库(例如mysql)中,然后在消息队列中发布一些数据.我的问题是:如果应用程序在数据库中存储后崩溃,我的数据将永远不会写入消息队列然后丢失(因此我的系统的最终一致性将无法保证).我怎么解决这个问题 ?

Voi*_*son 16

我有一个应用程序,我需要将一些数据存储在数据库(例如mysql)中,然后在消息队列中发布一些数据.我的问题是:如果应用程序在数据库中存储后崩溃,我的数据将永远不会写入消息队列然后丢失(因此我的系统的最终一致性将无法保证).我怎么解决这个问题 ?

在这种特殊情况下,答案是从数据库加载队列数据.

也就是说,您在用于写入数据的同一事务中编写需要排队到数据库的消息.然后,异步地,您从数据库中读取该数据,并将其写入队列.

请参阅Udi Dahan的" Reliable Messaging without Distributed Transactions".

如果应用程序崩溃,则恢复很简单 - 在重新启动期间,您将在数据库中查询所有未确认的消息,然后再次发送它们.

请注意,此设计确实希望消息的使用者至少设计一次.


Gor*_*off 5

评论太长了。

我假设你有一个无损消息队列,一旦你得到写入数据的确认,队列就保证有记录。

基本上,您需要一个带有可以回滚的事务或数据库中的状态的循环。交易的伪代码是:

  • 开始交易
  • 插入数据库
  • 写入消息队列
  • 当消息队列确认时,提交事务

就个人而言,我可能会使用以下状态来执行此操作:

  • 以“待处理”(或类似的)状态插入到数据库中
  • 写入消息队列
  • 当消息确认时,将状态更改为“已提交”(或类似的内容)

在从故障中恢复的情况下,您可能需要检查消息队列以查看是否有任何“待处理”记录实际写入队列。

  • 感谢您的回答,我还有一些问题: 1)如果我在提交事务之前在消息队列中写入,则队列中的消息可能会在事务提交之前被处理。2)如果我的ID是数据库生成的,我不能把它包含在队列中发布的消息中。 (3认同)