Besides being a database, Redis is also a message broker that supports typical pub/sub operations. In this story, we’ll dive into the world of Pub/Sub in Redis and explore its capabilities and limitations.
Pub/Sub in a nutshell
Pub/Sub stands for “Publish/Subscribe”. It is a pattern in computer programming that involves allowing messages to be sent from one component of an application to one or many other components without those components being directly connected or having a direct relationship with one another.
Think of it like a radio broadcaster. The “publisher” broadcasts audio, and the “subscribers” listen to the audio. The publisher does not need to know who the subscribers are, and the subscribers do not need to know who the publisher is. The only thing that matters is the message being broadcast.
In pub/sub, components can send messages to a central “topic” or “channel”, and other components can subscribe to that channel to receive those messages. This allows for decoupled communication between components and makes it easier to manage the flow of information in a complex system.
Pub/Sub in Redis
Redis implements the Pub/Sub pattern by providing a simple and efficient messaging system between clients. In Redis, clients can “publish” messages to a named channel, and other clients can “subscribe” to that channel to receive the messages.
When a client publishes a message to a channel, Redis delivers that message to all clients that are subscribed to that channel. This allows for real-time communication and the exchange of information between separate components of an application.
Redis Pub/Sub provides a lightweight, fast, and scalable messaging solution that can be used for various use cases, such as implementing real-time notifications, sending messages between microservices, or communicating between different parts of a single application.
Synchronous Communication
Redis Pub/Sub is synchronous. Subscribers and publishers must be connected at the same time in order for the message to be delivered.
Think of it as a radio station. You are able to listen to a station while you’re tuned into it. However, you’re incapable of listening to any message broadcast while your radio was off. Redis Pub/Sub will only deliver messages to connected subscribers.
This means that if one subscriber loses connection and this connection is restored later on, it won’t receive any missed messages or be notified about them. Therefore, it limits use cases to those that can tolerate potential message loss.
Fire & Forget
Fire & Forget is a messaging pattern where the sender sends a message without expecting an explicit acknowledgment from the receiver that the message was received. The sender simply sends the message and moves on to the next task, regardless of whether or not the message was actually received by the receiver.
Redis Pub/Sub is considered a “Fire & Forget” messaging system because it does not provide an explicit acknowledgment mechanism for confirming that a message was received by the receiver. Instead, messages are broadcast to all active subscribers, and it is the responsibility of the subscribers to receive and process the messages.
Fan-out Only
Redis Pub/Sub is fan-out only, meaning that when a publisher sends a message, it is broadcast to all active subscribers. All subscribers receive a copy of the message, regardless of whether they are specifically interested in the message or not.
No relation to the keyspace
Additionally, Pub/Sub has no relation to the key space. This means that a message published on database 10 will be heard by a subscriber on database 1. If you need scoping, Redis suggests prefixing the channel name (prod_mychannel, test_mychannel).
Putting our hands in the fire
Redis message brokering is implemented through the PUBLISH and SUBSCRIBE commands. The PUBLISH command allows the user to send a message to a specific channel, and the SUBSCRIBE command allows the user to listen to messages on a specific channel. This makes it easy to implement a publish-subscribe pattern in your application.
Channels are not explicitly created by the user. The channels are created automatically when the first message is published or a client subscribes to them.
In this example, we’ll open three connections with the same Redis server. Each connection will act as a different client.
Two of the connections will subscribe to the crazy_channel
, while the third one will publish messages to the same channel.
By doing that, we expect our messages to be delivered to both subscribers as soon as they’re published by the publisher.
Connecting to the Redis server
If you don’t have an instance of Redis already running, make sure you check my tutorial on how to run Redis locally with Docker:
Open three terminal windows and connect to your Redis server in each one of them. If you followed my previous tutorial, you can do it by running the following command:
docker exec -it redis-stack redis-cli
Subscribing to a channel
To subscribe to a channel, we need to issue the SUBSCRIBE
command with the channel’s name as the argument. In the first two windows, let’s issue the following command:
SUBSCRIBE crazy_channel
Publishing to a channel
You can publish a message to a channel using the PUBLISH command. The PUBLISH command takes two arguments: the name of the channel and the message to be sent.
In the third window, let’s publish “This channel is hella crazy”. We can do it by issuing the following command
PUBLISH crazy_channel "This channel is hella crazy"
Let’s publish another message:
PUBLISH crazy_channel "Hell yeah! It is!"
Crazy! We can see that it worked. As soon as we hit enter, our messages popped up in the clients that were subscribing to our channels. Let’s analyze what happened there.
You can see that every time a message popped up, three lines were printed into the terminal. We ended up with three blocks of three lines each.
Each of these blocks represents an event notification. Each event notification is a tuple that consists of three elements:
- The type of the event.
- The channel that the event applies to.
- Additional data associated with the event.
In this example, we are subscribing to the channel “crazy_channel”, so the first event notification is a “subscribe” event, which indicates that we have successfully subscribed to the channel. The second element is the channel name, “crazy_channel”, and the third element is the number of channels we are currently subscribed to, which is 1.
The following event notifications are “message” events, which indicate that messages have been received on the subscribed channel. The second element is the channel name, “crazy_channel”, and the third element is the actual message data, which is a string representing the message content.
Other commands
When subscribing via the Redis command line interface, you cannot issue any other commands to your server. However, if you’re subscribing through another interface, telnet, for example, you can still issue commands that are related to message subscription. Here are the commands allowed in the context of a subscriber:
Command | Description | Example |
---|---|---|
SUBSCRIBE | Subscribes the client to one or more channels | SUBSCRIBE channel_name |
PSUBSCRIBE | Subscribes the client to one or more channels using pattern_matching | PSUBSCRIBE channel_pattern |
SSUBSCRIBE | Subscribes the client to one more channels in a Redis Cluster shard | SSUBSCRIBE channel_name |
UNSUBSCRIBE | Unsubscribe the client from one or more channels | UNSUBSCRIBE channel_name |
PUNSUBSCRIBE | Unsubscribes the client from one or more channels using pattern matching | PUNSUBSCRIBE channel_pattern |
SUBSUBSCRIBE | Unsubscribes the client from one or more channels in a Redis Cluster shard | SUBSUBSCRIBE channel_name |
PING | Tests the connection to the Redis Server | PING |
RESET | Resets the connection to the Redis server | RESET |
QUIT | Closes the connection to the Redis Server | QUIT |
Conclusion
Redis provides a simple and powerful solution for real-time messaging systems through its Pub/Sub functionality.
It’s lightweight, easy to implement, and integrate into existing systems. It can also support a large number of subscribers and handle high volumes of messages with low latency. Besides that, messages are delivered in the order that they are published.
It’s important to note that the use cases are limited to those that can tolerate message loss, and that don’t require explicit acknowledgment of messages by the receiver. These limitations should be considered when determining the suitability of Redis Pub/Sub as a message broker for a particular use case.
However, these limitations can be overcome when using Redis Streams, the subject of our next story:
Leave a Reply