Before we look at what Single Active Consumer is, let's review how a normal queue with multiple consumers behaves.
We see that with three consumers, each consumer competes for the messages in the queue. With a prefetch of 1, the 10 messages are evenly distributed across
If message processing cannot keep up with message ingress to a queue, the standard way of scaling the processing is to add more consumers and parallelize the work. This is a simple and effective method of scaling.
Fig 1. Three consumers with prefetch (QoS) of 1.
Single Active Consumer
When we enable SAC on a queue, the queue no longer permits competing consumers. One SAC enabled queue can have only one consumer actively consuming messages at a time. Additional consumers are in the Waiting state in case the first consumer goes away.
When consumer C1 fails or shutdowns, another consumer will become the "active" consumer and consumption will resume.
Fig 2. Three consumers subscribed to a SAC enabled queue. All messages get delivered to the active consumer.
Fig 3. C1 goes away and C3 changes from Waiting to Active.
Highly Available Consumer
The principal reason for SAC is when we need a single highly available consumer.
Sometimes we only need or want a single consumer to do the work of processing messages but we need that work to be highly available. SAC enables this by allowing multiple consumers but only allowing one consumer to do the work and allowing another consumer to take over the moment the active consumer goes down. Also known as Active/Standby or Active/Passive.
Reasons for only wanting a single consumer doing work at a time:
- Data consistency is only possible when one application is doing work. Two applications working at the same time tread on each other.
- Concurrency issues in other systems, such as database deadlocks.
- Third party systems only allow one process at a time to interact with it.
- The consumer needs to perform computation based on a window of events and must receive all messages.
- Data locality. Data is cached in memory for performance and to reduce load on other systems. All messages need to go through the same application.
- Can optimize prefetch and multiple flag usage without introducing message ordering issues (See Notes on High Prefetch and Multiple Flag Usage below)
There can be multiple reasons to need a single active consumer and require that the service is highly available at the same time.
Notes On High Prefetch and Multiple Flag Usage
A side effect of having a single consumer for queue is that you can leverage prefetch and the multiple flag on the consumer side in order to increase message throughput without affecting message ordering.
The slowest approach is: prefetch 1, acks with multiple=false
- Broker sends a single message to C1
- Broker sends a single message to C2
- C1 acks its message
- Broker sends a single message to C1
- C2 acks its message
- Broker sends C2 a message
- ........
This message-ack ping pong massively reduces throughput.
The fastest is to have a high prefetch and use the multiple flag:
- Broker sends 2000 messages to C1
- Broker sends 2000 messages to C2
- C1 acks 1000 messages with one ack (multiple=true)
- Broker sends 1000 messages to C1
- C2 acks 1000 messages with one ack (multiple=true)
- Broker sends 1000 messages to C2
- C1 acks 1000 messages with one ack (multiple=true)
- .....
This allows batching of messages which greatly increases throughput. Read more about how to set prefetch here.
The problems with this configuration are:
- Processing order can be far from FIFO when competing consumers are involved
- Large numbers of messages get received twice when a connection failure occurs.
We can’t afford the duplication of messages during a connection failure but if you only have a single consumer, the message ordering issues go away. When a queue has a single consumer, you can fully optimize prefetch and multiple flag usage without worrying about message ordering. This reduces the load on the broker also. But you need a situation where a single consumer can process messages fast enough to cope with the ingress rate.
Coming in release 3.8
Single Active Consumer is coming in RabbitMQ 3.8, to be released this year. The only change required is on declaring the queue, setting SAC to enabled. You can read more about this upcoming feature on the Next RabbitMQ site: www.rabbitmq.com/consumers.html#single-active-consumer
Please send us an email at contact@cloudamqp.com if you have any questions or feedback to this blog post.