Pub/Sub (Publish/Subscribe) là cơ chế messaging cho phép các phần mềm giao tiếp với nhau theo mô hình real-time. Đây là nền tảng cho chat apps, notifications, và event-driven architecture.

Pub/Sub là gì?
Pub/Sub hoạt động như đài phát thanh:
- Publisher — Đài phát thanh, phát sóng chương trình
- Subscriber — Người nghe radio, tune vào kênh yêu thích
- Channel — Tần số radio (ví dụ:
news,sports)
Đặc điểm quan trọng:
- ✅ Decoupled — Publisher không cần biết ai đang subscribe
- ✅ Real-time — Message được gửi ngay lập tức
- ❌ Fire-and-forget — Nếu không có subscriber, message bị mất
- ❌ Không persist — Messages không được lưu trữ
Các lệnh cơ bản
Subscribe (Đăng ký nhận tin)
# Terminal 1: Subscribe vào channel
SUBSCRIBE news
# 1) "subscribe"
# 2) "news"
# 3) (integer) 1 → số channels đang subscribe
# Chờ messages...
# Khi có message:
# 1) "message"
# 2) "news"
# 3) "Breaking: Redis 8.0 released!"
Publish (Gửi tin)
# Terminal 2: Publish message
PUBLISH news "Breaking: Redis 8.0 released!"
# (integer) 1 → số subscribers nhận được message
# Publish vào channel không có subscriber
PUBLISH news "Hello?"
# (integer) 0 → message bị mất!
Subscribe nhiều channels
# Subscribe nhiều channels cùng lúc
SUBSCRIBE news sports weather
# Unsubscribe
UNSUBSCRIBE news
# Unsubscribe tất cả
UNSUBSCRIBE
Pattern Subscribe
Dùng PSUBSCRIBE để subscribe theo pattern:
# Subscribe tất cả channels bắt đầu bằng "user:"
PSUBSCRIBE user:*
# Khi có message trên "user:1001:notifications":
# 1) "pmessage"
# 2) "user:*" → pattern
# 3) "user:1001:notifications" → channel
# 4) "New message!" → message
# Subscribe nhiều patterns
PSUBSCRIBE user:* order:* payment:*
# Unsubscribe pattern
PUNSUBSCRIBE user:*
Use Cases thực tế
1. Real-time Notifications
# User subscribe vào channel của mình
SUBSCRIBE notifications:user:1001
# Khi có sự kiện, publish notification
PUBLISH notifications:user:1001 "{\"type\": \"order_shipped\", \"order_id\": 456}"
PUBLISH notifications:user:1001 "{\"type\": \"new_message\", \"from\": \"Tan\"}"
2. Chat Application
# User join room
SUBSCRIBE chat:room:42
# Gửi tin nhắn
PUBLISH chat:room:42 "{\"user\": \"Tan\", \"msg\": \"Hello everyone!\"}"
# Tất cả users trong room sẽ nhận được tin nhắn
3. Cache Invalidation
# Service A: Subscribe cache invalidation
PSUBSCRIBE cache:invalidations:*
# Service B: Khi data thay đổi, invalidate cache
PUBLISH cache:invalidations:user "user:1001"
PUBLISH cache:invalidations:product "product:555"
# Service A nhận được → xóa cache tương ứng
4. Event Broadcasting
# Microservices subscribe events quan tâm
# Email Service
SUBSCRIBE events:user_registered
# Analytics Service
SUBSCRIBE events:user_registered events:order_created
# Notification Service
PSUBSCRIBE events:*
# Khi user đăng ký
PUBLISH events:user_registered "{\"user_id\": 1001, \"email\": \"[email protected]\"}"
Pub/Sub với Programming Languages
Python
import redis
import threading
r = redis.Redis()
# Subscriber trong thread riêng
def subscriber():
p = r.pubsub()
p.subscribe("news")
for message in p.listen():
if message["type"] == "message":
print(f"Received: {message[\"data\"].decode()}")
threading.Thread(target=subscriber, daemon=True).start()
# Publisher
r.publish("news", "Hello from Python!")
Node.js
const redis = require("redis");
// Tạo 2 clients (1 cho subscribe, 1 cho publish)
const subscriber = redis.createClient();
const publisher = redis.createClient();
// Subscriber
subscriber.subscribe("news");
subscriber.on("message", (channel, message) => {
console.log(`Received from ${channel}: ${message}`);
});
// Publisher
publisher.publish("news", "Hello from Node.js!");
Hạn chế và giải pháp
| Hạn chế | Giải pháp |
|---|---|
| Messages không persist | Dùng Redis Streams |
| Không có consumer groups | Dùng Redis Streams |
| Không retry khi fail | Implement retry logic ở application |
| Fire-and-forget | Kết hợp với persistent queue (RabbitMQ, Kafka) |
Pub/Sub vs Streams
| Tiêu chí | Pub/Sub | Streams |
|---|---|---|
| Persistence | ❌ Không | ✅ Có |
| Consumer Groups | ❌ Không | ✅ Có |
| Message History | ❌ Không | ✅ Có |
| Độ phức tạp | ✅ Đơn giản | ❌ Phức tạp hơn |
| Use case | Real-time notifications | Event sourcing, logs |
Best Practices
- Biết giới hạn Fire-and-Forget — Messages không persist, subscriber offline sẽ mất
- Dùng pattern subscribe —
PSUBSCRIBEcho wildcard channels - Xử lý disconnect — Subscriber phải reconnect tự động
- Consider Streams — Cần persistence? Dùng Redis Streams thay thế
- Monitor subscriber count — Dùng
PUBSUB NUMSUB
Bước tiếp theo
Bạn đã nắm vững Pub/Sub trong Redis! Tiếp theo, chúng ta sẽ tìm hiểu về Transactions — cách nhóm nhiều lệnh thành một atomic operation.