Pub/Sub trong Redis: Giao tiếp Real-time giữa các Services

Photo of author

Văn Ngọc Tân

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.

Real-time messaging between services using Redis Pub/Sub
Pub/Sub cho phép giao tiếp real-time giữa các microservices

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 subscribePSUBSCRIBE cho 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.

👉 Bài tiếp theo: Transactions trong Redis (MULTI/EXEC)

0 0 đánh giá
Đánh giá bài viết
Theo dõi
Thông báo của
guest
0 Góp ý
Cũ nhất
Mới nhất Được bỏ phiếu nhiều nhất
Phản hồi nội tuyến
Xem tất cả bình luận