Search code examples
rabbitmqamqp

RabbitMQ / AMQP design: How can I have some messages to be processed by one consumer, and but observed all consumers?


I have an application that has 3 instances/replicas (three applications of the same kind are run simultaneously). They all consume the same queue, so RabbitMQ delivers messages in round robin fashion. All three instances share a single database that they r/w to.

This works great when the queue receives, let's say, new-user message, delivers it to one instance, and that instance saves the user to the common database.

The problem: Given a message new-user, I want one instance to save it to the database (as before), but now I want all three to invalidate their caches. So I actually need all instances to receive the same event, but only one of them to act differently.

How can you design a system that allows these requirements?

The best way I can think of is to have two exchanges (fanout and direct), new-user message to be sent to a separate application which duplicates it and sends it to fanout and direct exchanges. All instances listen to both exchanges, and depending on the message handler, decides on what to do (if the message is from fanout exchange: invalidate the cache, if it's from direct exchange, well, only one would receive it anyways).


Solution

  • There can be a problem with your approach. If messages from fanout exchange will arrive before user was actually created, your instances may invalidate cache too early. I think you should do the following:

    • Have direct exchange and worker queue where all your user creators are getting messages in round robin, like you have it now.
    • When instance created a user, it sends a message user created to a topic or fanout exchange, where all user creators are listening. Then all of the instances (including sender) will receive the user created event and will invalidate their cache.