Redis Pub/Sub implements the publish/subscribe messaging paradigm where senders (publishers) send messages to channels without knowledge of subscribers, and receivers (subscribers) receive messages from channels they’re interested in.
PUBLISH
Posts a message to a channel.
Syntax
The channel name to publish to.
The number of clients that received the message. In Redis Cluster, only clients connected to the same node are counted.
Time Complexity: O(N+M) where N is the number of clients subscribed to the channel and M is the total number of subscribed patterns.
Examples
redis> PUBLISH news "Breaking news: Redis is fast!"
(integer) 0
redis> PUBLISH news "Another update"
(integer) 2
SUBSCRIBE
Subscribes to one or more channels.
Syntax
SUBSCRIBE channel [channel ...]
The channel name(s) to subscribe to.
Streams of messages from subscribed channels. Format:
["subscribe", channel, num_subscribed] - Subscription confirmation
["message", channel, message_data] - Published message
["unsubscribe", channel, num_remaining] - Unsubscription confirmation
Time Complexity: O(N) where N is the number of channels to subscribe to.
Examples
redis> SUBSCRIBE news
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "news"
3) (integer) 1
1) "message"
2) "news"
3) "Breaking news: Redis is fast!"
Once a client enters subscribed mode with SUBSCRIBE, it cannot issue other commands except SUBSCRIBE, PSUBSCRIBE, UNSUBSCRIBE, PUNSUBSCRIBE, PING, and QUIT.
PSUBSCRIBE
Subscribes to channels matching patterns.
Syntax
PSUBSCRIBE pattern [pattern ...]
The glob-style pattern(s) to match channel names:
* matches any characters
? matches a single character
[abc] matches one character from the set
Streams of messages from channels matching patterns. Format:
["psubscribe", pattern, num_subscribed] - Subscription confirmation
["pmessage", pattern, channel, message_data] - Published message
["punsubscribe", pattern, num_remaining] - Unsubscription confirmation
Time Complexity: O(N) where N is the number of patterns to subscribe to.
Examples
redis> PSUBSCRIBE news.*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "news.*"
3) (integer) 1
1) "pmessage"
2) "news.*"
3) "news.tech"
4) "New tech article published"
1) "pmessage"
2) "news.*"
3) "news.sports"
4) "Match results are in"
Additional Pub/Sub Commands
- UNSUBSCRIBE: Unsubscribe from channels
- PUNSUBSCRIBE: Unsubscribe from patterns
- PUBSUB CHANNELS: List active channels
- PUBSUB NUMSUB: Get subscriber count per channel
- PUBSUB NUMPAT: Get pattern subscription count
- PUBSUB SHARDCHANNELS: List active shard channels
- PUBSUB SHARDNUMSUB: Get shard channel subscriber count
- SPUBLISH: Publish to shard channel
- SSUBSCRIBE: Subscribe to shard channels
- SUNSUBSCRIBE: Unsubscribe from shard channels
Use Cases
Real-Time Notifications
Send notifications to users:
# Publisher sends notification
redis> PUBLISH notifications:user:1000 "You have a new message"
(integer) 1
# Subscriber receives (in another client)
redis> SUBSCRIBE notifications:user:1000
1) "subscribe"
2) "notifications:user:1000"
3) (integer) 1
1) "message"
2) "notifications:user:1000"
3) "You have a new message"
Chat Application
Implement chat rooms:
# User joins chat room
redis> SUBSCRIBE chat:room:general
1) "subscribe"
2) "chat:room:general"
3) (integer) 1
# User sends message (from another client)
redis> PUBLISH chat:room:general "Alice: Hello everyone!"
(integer) 5
# All subscribers receive
1) "message"
2) "chat:room:general"
3) "Alice: Hello everyone!"
Event Broadcasting
Broadcast system events:
# Subscribe to all system events
redis> PSUBSCRIBE system.*
1) "psubscribe"
2) "system.*"
3) (integer) 1
# Publish different event types
redis> PUBLISH system.startup "Server started"
(integer) 1
redis> PUBLISH system.error "Disk space low"
(integer) 1
redis> PUBLISH system.shutdown "Server stopping"
(integer) 1
Cache Invalidation
Notify cache invalidation:
# Subscribe to cache invalidation events
redis> SUBSCRIBE cache:invalidate
# When data changes, publish invalidation
redis> SET user:1000:profile "{updated_data}"
OK
redis> PUBLISH cache:invalidate "user:1000:profile"
(integer) 3
# All cache instances receive and clear
Live Dashboard
Update dashboards in real-time:
# Dashboard subscribes to metrics
redis> SUBSCRIBE metrics:realtime
# Metrics service publishes updates
redis> PUBLISH metrics:realtime "{cpu:45,memory:60,requests:1500}"
(integer) 10
Best Practices
- Fire and Forget: PUBLISH doesn’t guarantee delivery
- No Persistence: Messages are not stored
- Blocking: Subscribers are in blocking mode
- Pattern Matching: PSUBSCRIBE is slower than SUBSCRIBE
Reliability Considerations
Standard Pub/Sub
Streams Alternative
Fast but unreliable:# Messages lost if no subscribers
redis> PUBLISH channel "message"
(integer) 0
# Messages lost if subscriber disconnects
Use for: Real-time, non-critical notifications Persistent and reliable:# Messages persist
redis> XADD channel * message "data"
"1640000000000-0"
# Consumers can read history
redis> XREAD STREAMS channel 0
Use for: Critical messages, event sourcing
Connection Management
- Maintain persistent connections for subscribers
- Handle reconnection with resubscription
- Monitor connection health with PING
- Use connection pools wisely
Patterns
Fan-Out Messaging
One publisher, many subscribers:
# Publisher
redis> PUBLISH broadcasts "Important announcement"
(integer) 100
# All 100 subscribers receive the message
Topic Routing
Route messages by topic:
# Subscribe to specific topics
redis> SUBSCRIBE news.tech news.sports
# Or use patterns
redis> PSUBSCRIBE news.*
# Publisher sends to specific topics
redis> PUBLISH news.tech "New gadget released"
redis> PUBLISH news.sports "Championship results"
Presence Detection
Detect online users:
# Subscribe to presence channel
redis> SUBSCRIBE presence
# Users publish when online
redis> PUBLISH presence "user:1000:online"
redis> PUBLISH presence "user:1001:online"
redis> PUBLISH presence "user:1000:offline"
Microservices Communication
Service-to-service messaging:
# Service A subscribes to orders
redis> SUBSCRIBE orders.new
# Service B publishes new orders
redis> PUBLISH orders.new "{order_id:1000,customer:alice}"
# Service A processes order
Command Broadcast
Broadcast commands to workers:
# Workers subscribe to commands
redis> SUBSCRIBE worker:commands
# Admin broadcasts command
redis> PUBLISH worker:commands "reload_config"
# All workers reload configuration
Pub/Sub vs Other Patterns
| Feature | Pub/Sub | Streams | Lists |
|---|
| Persistence | No | Yes | Yes |
| History | No | Yes | Yes |
| Delivery | At most once | At least once | Exactly once |
| Speed | Fastest | Fast | Fast |
| Use Case | Real-time | Events | Queues |
Advanced Patterns
Namespace Isolation
Isolate channels by namespace:
# Development environment
redis> SUBSCRIBE dev:notifications
# Production environment
redis> SUBSCRIBE prod:notifications
# Prevent cross-environment messages
Message Filtering
Filter messages on client side:
# Subscribe to all
redis> PSUBSCRIBE events.*
# Filter in application code
# if message matches criteria:
# process(message)
# else:
# ignore(message)
Hybrid Approach
Combine Pub/Sub with persistence:
# Publish to both
redis> PUBLISH realtime:updates "data"
redis> XADD persistent:updates * data "data"
# Realtime subscribers get instant updates
# Historical consumers can replay from stream
Subscription Management
Track active subscriptions:
# List active channels
redis> PUBSUB CHANNELS
1) "news"
2) "chat:room:general"
# Count subscribers
redis> PUBSUB NUMSUB news chat:room:general
1) "news"
2) (integer) 5
3) "chat:room:general"
4) (integer) 12
# Count pattern subscriptions
redis> PUBSUB NUMPAT
(integer) 3
Common Issues
Message Loss
Pub/Sub messages are lost if:
- No subscribers are listening
- Subscriber disconnects
- Network issues occur
- Subscriber is slow (buffer overflow)
Solution: Use Streams for critical messages
Client Blocking
Subscribers cannot execute other commands:
# After SUBSCRIBE, this fails:
redis> SUBSCRIBE channel
redis> GET key
(error) ERR only (P)SUBSCRIBE / (P)UNSUBSCRIBE / PING / QUIT allowed in this context
Solution: Use separate connections for Pub/Sub
Pattern Overhead
Pattern subscriptions check every published message:
# Many patterns slow down publishing
redis> PSUBSCRIBE pattern1 pattern2 pattern3 ...
Solution: Use specific channels when possible
Integration Examples
Python Example
import redis
# Subscriber
r = redis.Redis()
p = r.pubsub()
p.subscribe('news')
for message in p.listen():
if message['type'] == 'message':
print(f"Received: {message['data']}")
# Publisher (separate process)
r = redis.Redis()
r.publish('news', 'Breaking news!')
Node.js Example
const redis = require('redis');
// Subscriber
const sub = redis.createClient();
sub.subscribe('news');
sub.on('message', (channel, message) => {
console.log(`Received from ${channel}: ${message}`);
});
// Publisher (separate client)
const pub = redis.createClient();
pub.publish('news', 'Breaking news!');
Monitoring
Monitor Pub/Sub activity:
# Monitor all commands (including PUBLISH)
redis> MONITOR
OK
1640000000.123456 [0 127.0.0.1:12345] "PUBLISH" "channel" "message"
# Check active channels
redis> PUBSUB CHANNELS
# Check subscriber counts
redis> PUBSUB NUMSUB channel1 channel2
# Check pattern subscriptions
redis> PUBSUB NUMPAT