Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Integrating RabbitMQ with database transactions

Tags:

Imagine the situation:

var txn = new DatabaseTransaction();  var entry = txn.Database.Load<Entry>(id); entry.Token = "123"; txn.Database.Update(entry);  PublishRabbitMqMessage(new EntryUpdatedMessage { ID = entry.ID });  // A bit more of processing  txn.Commit(); 

Now a consumer of EntryUpdatedMessage can potentially get this message before the transaction txn is committed and therefore will not be able to see the update.

Now, I know that RabbitMQ does support transactions by itself, but we cannot really use them because we create a new IModel for each publish and having a per-thread model is really cumbersome in our scenario (ASP.NET web application).

I thought of having a list of messages due to be published when a DB transaction is committed, but that's a really smelly solution.

What is the correct way of handling this?

like image 244
Anton Gogolev Avatar asked Jul 23 '13 12:07

Anton Gogolev


People also ask

Does RabbitMQ use a database?

Every RabbitMQ node has a data directory that stores all the information that resides on that node. A data directory contains two types of data: definitions (metadata, schema/topology) and message store data.

Is RabbitMQ transactional?

Transactions in RabbitMQ concern only messages. So, it works only when a message is published or acknowledged. It's important to underline the acknowledged word because it doesn't mean the same as consumed. Strictly speaking, when a message is rolled back after acknowledging, it's not requeued.

Does RabbitMQ use MySQL?

The default for messaging is RabbitMQ and the default database is MySQL. They are known workhorses in the industry and in our experience they generally suffice even for large deployments in terms of scalability. In theory, any database supporting SQLAlchemy will do, but most users stick with the default.

Does RabbitMQ support message ordering?

Message ordering guaranteesRabbitMQ offers stronger guarantees since release 2.7. 0. Messages can be returned to the queue using AMQP methods that feature a requeue parameter (basic. recover, basic.


1 Answers

RabbitMQ encourages you to use publisher confirms rather than transactions. Transactions do not perform well.

In any case, transactions don't usually work very well with a service oriented architecture. It's better to adopt an 'eventually consistent' approach, where failure can be retried at a later date and duplicate idempotent messages are ignored.

In your example I would do the database update and commit it before publishing the message. When the publisher confirm returns, I would update a field in the database record to indicate that the message had been sent. You can then have a sweeper process come along later, check for unsent messages and send them on their way. If the message did get through, but for some reason the confirm, or subsequent database write failed, you will get a duplicate message. But that won't matter, because you've designed your messages to be idempotent.

like image 136
Mike Hadlow Avatar answered Sep 20 '22 04:09

Mike Hadlow