Pub/Sub

Back to Glossary

Pub/Sub Defined

Pub/Sub (short for publish/subscribe) is a messaging pattern in which senders of messages, called publishers, do not program the messages to be sent directly to specific receivers, called subscribers. Instead, messages are categorized into classes or topics, and subscribers express interest in one or more of these topics by registering with the pub/sub system. Publishers and subscribers are decoupled from each other, and do not need to be aware of each other’s existence. When a publisher sends a message, it is transmitted to all subscribers who have expressed interest in the message’s topic. This allows for flexible and scalable communication between components or services in a distributed system, without requiring direct connections between them. Pub/Sub is commonly used in cloud computing and Internet of Things (IoT) architectures, among other applications.

Python Redis Pub/Sub

Python is a programming language that provides a Redis client library, which allows Python developers to interact with Redis, an in-memory data structure store. Redis provides a publish/subscribe (pub/sub) messaging system that allows clients to subscribe to channels and receive messages when messages are published to those channels.

Python can be used to implement pub/sub functionality using Redis by sending PUBLISH commands to publish messages and SUBSCRIBE commands to subscribe to channels. The Redis client library for Python provides a convenient way to handle pub/sub messaging in Python applications.

Commands for handling pub/sub in Redis

CommandExample Use and Description
SUBSCRIBESUBSCRIBE channel [channel …] – Subscribes to the given channels
UNSUBSCRIBEUNSUBSCRIBE [channel [channel …]] – Unsubscribes from the provided channels, or unsubscribes all channels if no channel is given
PUBLISHPUBLISH channel message – Publishes a message to the given channel
PSUBSCRIBEPSUBSCRIBE pattern [pattern …] – Subscribes to messages broadcast to channels that match the given pattern
PUNSUBSCRIBEPUNSUBSCRIBE [pattern [pattern …]] – Unsubscribes from the provided patterns, or unsubscribes from all subscribed patterns if none are given
Credit: Redis in Action

To effectively showcase the feature, it’s more convenient to utilize a helper thread to handle PUBLISHing due to the implementation of PUBLISH and SUBSCRIBE commands on the Python end.

Pub/Sub best Practices in Redis

Aside from data storage, as previously stated, Redis can be used as a Publisher/Subscriber platform. In this pattern, publishers can issue messages to any number of subscribers on a channel. These messages are fire-and-forget, in that if a message is published and no subscribers exists, the message evaporates and cannot be recovered.

Once subscribed to a channel, the client is put into subscriber mode and no commands can be issued by the client. In this way, the client has become read-only. Publishing has no such limitation.

More than one channel can be subscribed to at a time. Let’s start by subscribing to two channels weather and sports using the SUBSCRIBE command.

> SUBSCRIBE weather sports
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "weather"
3) (integer) 1
1) "subscribe"
2) "sports"
3) (integer) 2

In a separate client (a separate terminal for our example) we can publish items to either of these channels. We do this by running the PUBLISH command:

> PUBLISH sports oilers/7:leafs/1
(integer) 1

The first argument is the channel and the second argument is the message. The message can be anything, in this case, it’s an encoded sports score. It returns the number of clients that it will be delivered to. Back in the subscriber mode client, we’ll instantly see the message:

1) "message"
2) "sports"
3) "oilers/7:leafs/1"

The response has three elements: the notice that’s a message, followed by the channel and finally the message itself. The client returns to listening immediately after the message is received. Flipping back to the other we can publish another message:

> PUBLISH weather snow/-4c
(integer) 1

In the other client we’ll see the same format but with another channel and event:

1) "message"
2) "weather"
3) "snow/-4c"

Let’s issue publish to a channel that no one is subscribing to:

> PUBLISH currency CADUSD/0.787
(integer) 0

Since we don’t have any clients listening to the channel currency the return is 0. This message is now gone and clients that subsequently subscribe to the currency channel will not be notified of this message – the message was fired and how it has been forgotten.

Aside from subscribing to individual channels, Redis allows for pattern-based subscriptions. The glob-style patterns and are enabled by the PSUBSCRIBE command:

> PSUBSCRIBE sports:*

This will get messages for any channel that starts with “sports:*”. In the other client, issue the following commands:

> PUBLISH sports:hockey oilers/7:leafs/1
(integer) 1
> PUBLISH sports:basketball raptors/33:pacers/7
(integer) 1
> PUBLISH weather:edmonton snow/-4c
(integer) 0

Note how the first two commands returned 1 versus the last command which has a 0. Even though we have no direct subscribers of sports:hockey or sports:basketball, it is still picked up as being received by the pattern subscription. Back on our subscribed client, we can see the results are returned only for the channels that match the pattern.

1) "pmessage"
2) "sports:*"
3) "sports:hockey"
4) "oilers/7:leafs/1"
1) "pmessage"
2) "sports:*"
3) "sports:basketball"
4) "raptors/33:pacers/7"

This response is a little different from the straight SUBSCRIBE response as it has both the matched pattern (2) and the actual channel named (3).