What is a Redis Queue?
With its support for list and other data structures, Redis works well as a message queue. When used as a queue, Redis efficiently manages multiple tasks in a line, ready for processing. These tasks could be messages, data flows, or chunks of streaming video to be executed immediately or at a later scheduled time. With the ability to handle distributed jobs and messages, a Redis queue is perfect for applications that require top-tier performance, scalability, and reliability.
What is Redis Queue?
A Redis queue is the virtual equivalent of a real-world queue or line. Instead of people waiting in line, a Redis queue is made up of tasks, messages, or other data waiting their turn. As a versatile in-memory data store, Redis isn't strictly a queuing system. However, its flexible list data structure makes it easy to build and manage powerful queues.
How does Redis Queue work?
As with queues in other programming and computer science concepts, Redis queues operate on the First-In, First-Out (FIFO) principle. In the real-world example of people waiting in line, the person at the front of the queue is the first to enter. Once in, they are the first to exit. Items waiting to be processed in a Redis queue follow the same principle.
Redis provides queue commands to add or remove items from a queue. This includes:
- LPUSH (left push) adds an item to the left (beginning) of a queue.
- RPUSH (right push) adds an item to the right (end) of a queue.
- LPOP (left pop) removes the item at the left (beginning) of a queue and returns it to the caller.
- RPOP (right pop) removes the item at the right (end) of a queue and returns it to the caller.
Redis offers other useful queue management functions. This includes blocking queues, which stops polling on an empty queue until it has tasks to process. A reliable queue pattern can also be built on top of these commands: rather than popping an item outright, LMOVE (formerly RPOPLPUSH) atomically moves it into a separate processing list, so the item isn't lost if the consumer crashes before finishing the job. Note that this hand-rolled pattern is distinct from Redisson PRO's Reliable Queue feature, covered below. Redis also supports the publish/subscribe (pub/sub) messaging pattern, which is useful when queued messages must be sent to multiple channel subscribers. The pub/sub paradigm is perfect for social media apps, collaborative workspaces, and any application that depends on timely notifications. As subscribers, end users can subscribe to multiple channels and receive notifications from each channel.
Redis Queue Use Cases
The Redis queue is sometimes called "the Swiss Army knife of data processing" because it's suitable for a wide range of applications and functions. As a task scheduler, it organizes and executes tasks at specific times or intervals, ensuring applications send reminders or perform background jobs on time.
The queue also works well for rate limiting, which controls the flow of requests to protect services or APIs from being overwhelmed. The pub/sub capabilities make it perfect for message brokering in distributed systems, as messages are delivered reliably across multiple clusters—perfect for chat applications or collaborative programs.
In distributed environments, the Redis queue helps control the order and flow of task processing across multiple servers or regional clusters. In fact, Redis queues are a good fit for any high-performance or high-availability application that manages complex data flows.
Redis Queue on Java
Redisson provides multiple implementations for Java developers who want to build applications around the powerful feature set of Redis queues.
The Redisson RQueue object implements Redis queues using the java.util.Queue interface. Here's a code sample to create a queue, add an item, inspect the head of the queue without removing it (peek), and then retrieve and remove the head of the queue (poll):
RQueue<SomeObject> queue = redisson.getQueue("anyQueue");
queue.add(new SomeObject());
SomeObject obj = queue.peek();
SomeObject someObj = queue.poll();
And here's how to set up a blocking queue with the RBlockingQueue object:
RBlockingQueue<SomeObject> queue = redisson.getBlockingQueue("anyQueue");
queue.offer(new SomeObject());
SomeObject obj = queue.peek();
SomeObject polledObj = queue.poll();
SomeObject timedObj = queue.poll(10, TimeUnit.MINUTES);
The poll, pollFromAny, pollLastAndOfferFirstTo, and take methods automatically resubscribe during re-connection to a Redis server or failover.
RBoundedBlockingQueue is a distributed BoundedBlockingQueue for Java that implements the java.util.concurrent.BlockingQueue interface. BoundedBlockingQueue's size is limited by Redis to 4,294,967,295 elements, making it appropriate for the largest applications.
Queue capacity should be defined once by the trySetCapacity() method before usage, like so:
RBoundedBlockingQueue<SomeObject> queue = redisson.getBoundedBlockingQueue("anyQueue");
// returns `true` if capacity set successfully and `false` if it already set.
queue.trySetCapacity(2);
queue.offer(new SomeObject(1));
queue.offer(new SomeObject(2));
// will be blocked until free space is available in the queue
queue.put(new SomeObject());
SomeObject obj = queue.peek();
SomeObject someObj = queue.poll();
SomeObject ob = queue.poll(10, TimeUnit.MINUTES);
Redisson also allows developers to bind listeners per RQueue object. Here's a look at the classes and their corresponding event descriptions:
Listener class name |
Event description |
org.redisson.api.listener.TrackingListener |
Element created/removed/updated after read operation |
org.redisson.api.listener.ListAddListener |
Element created |
org.redisson.api.listener.ListRemoveListener |
Element removed |
org.redisson.api.ExpiredObjectListener |
RQueue object expired |
org.redisson.api.DeletedObjectListener |
RQueue object deleted |
Here's how to incorporate the listener in code:
RQueue<SomeObject> queue = redisson.getQueue("anyQueue");
int listenerId = queue.addListener(new DeletedObjectListener() {
@Override
public void onDeleted(String name) {
// ...
}
});
// ...
queue.removeListener(listenerId);
Reliable Queue for Java
The Redisson queue objects above are built on the standard Redis list, which means they inherit its limits: once an element is popped, it's gone. If the consumer crashes partway through processing, the message is lost, with no built-in way to retry it, prioritize it, or quarantine it after repeated failures. Ordering work by importance is covered separately in distributed priority queues in Java.
Redisson PRO addresses this with Reliable Queue, which adds exactly-once delivery, manual and automatic acknowledgments, negative acknowledgments (NACK) for failed processing, dead letter queues, message priority levels, visibility timeouts, deduplication, message headers, and configurable size limits for both messages and queues. For a full breakdown of these features with code samples, see Reliable Queue for Valkey and Redis, or go straight to the Reliable Queue documentation.