Redis Pub/Sub
Redis Pub/Sub (Publish/Subscribe) là một mô hình nhắn tin cho phép các thành phần trong hệ thống giao tiếp với nhau theo cách không đồng bộ. Nó hoạt động dựa trên cơ chế nhà xuất bản (publisher) gửi tin nhắn đến một kênh (channel) và người đăng ký (subscriber) nhận tin nhắn từ kênh đó mà không cần biết ai gửi. Dưới đây là giải thích chi tiết và dễ hiểu:
1. Cách Redis Pub/Sub hoạt động
Publisher: Gửi tin nhắn đến một kênh cụ thể bằng lệnh
PUBLISH
. Ví dụ:PUBLISH mychannel "Xin chào"
.Subscriber: Đăng ký để nhận tin nhắn từ một hoặc nhiều kênh bằng lệnh
SUBSCRIBE
hoặcPSUBSCRIBE
(cho mẫu kênh).Channel: Là tên định danh (string) để gửi/nhận tin nhắn. Tin nhắn được gửi đến kênh sẽ đến tất cả các subscriber của kênh đó.
Redis không lưu trữ tin nhắn sau khi gửi. Nếu subscriber không kết nối tại thời điểm tin nhắn được gửi, nó sẽ không nhận được tin nhắn.
2. Các lệnh cơ bản
PUBLISH channel message
: Gửi tin nhắn đến kênh. Ví dụ:SUBSCRIBE channel [channel ...]
: Đăng ký nhận tin nhắn từ một hoặc nhiều kênh. Ví dụ:Sau khi chạy lệnh này, client sẽ ở chế độ lắng nghe và nhận tin nhắn từ kênh
mychannel
.UNSUBSCRIBE [channel ...]
: Hủy đăng ký kênh.PSUBSCRIBE pattern [pattern ...]
: Đăng ký theo mẫu kênh (dùng ký tự wildcard như*
). Ví dụ:Nhận tin nhắn từ tất cả kênh bắt đầu bằng
news.
(nhưnews.sport
,news.tech
).PUNSUBSCRIBE [pattern ...]
: Hủy đăng ký mẫu kênh.PUBSUB
: Cung cấp thông tin về trạng thái Pub/Sub, ví dụ:PUBSUB CHANNELS
: Liệt kê các kênh đang hoạt động.PUBSUB NUMSUB channel
: Đếm số subscriber của kênh.
3. Ví dụ minh họa
Giả sử bạn có 2 terminal chạy Redis CLI:
Terminal 1 (Subscriber):
Terminal này sẽ chờ và hiển thị tin nhắn từ kênh mychannel
.
Terminal 2 (Publisher):
Kết quả ở Terminal 1:
4. Ứng dụng thực tế
Chat thời gian thực: Gửi tin nhắn đến các phòng chat (mỗi phòng là một kênh).
Thông báo sự kiện: Báo cáo trạng thái hệ thống, ví dụ: cập nhật đơn hàng, thông báo lỗi.
Cập nhật dữ liệu trực tiếp: Gửi dữ liệu mới (như giá chứng khoán) đến nhiều client.
Hệ thống phân tán: Điều phối công việc giữa các dịch vụ.
5. Ưu điểm
Nhẹ và nhanh: Redis Pub/Sub rất hiệu quả, phù hợp với các hệ thống thời gian thực.
Đơn giản: API dễ sử dụng, không cần cấu hình phức tạp.
Hỗ trợ mẫu kênh:
PSUBSCRIBE
cho phép linh hoạt trong việc lọc tin nhắn.
6. Hạn chế
Không lưu trữ tin nhắn: Nếu subscriber không hoạt động, tin nhắn sẽ bị mất (khác với các hệ thống như Kafka).
Không đảm bảo phân phối: Nếu kết nối bị gián đoạn, tin nhắn có thể không được gửi đến.
Không phù hợp với khối lượng lớn: Pub/Sub tối ưu cho các hệ thống nhỏ và trung bình, không thay thế được các message queue mạnh mẽ hơn.
1. Chuẩn bị
Cài Redis server trên máy của bạn và đảm bảo nó đang chạy (mặc định trên
localhost:6379
).Thêm thư viện Jedis vào dự án. Nếu dùng Maven, thêm dependency sau vào
pom.xml
:
2. Ví dụ code
Subscriber
Subscriber sẽ lắng nghe tin nhắn từ một kênh cụ thể (mychannel
). Chúng ta cần tạo một lớp kế thừa JedisPubSub
để xử lý các sự kiện khi nhận được tin nhắn.
Giải thích:
JedisPubSub
là một lớp trừu tượng cung cấp các phương thức để xử lý sự kiện nhưonMessage
,onSubscribe
, v.v.jedis.subscribe(pubSub, "mychannel")
đăng ký lắng nghe kênhmychannel
. Phương thức này chặn luồng (blocking) cho đến khi hủy đăng ký.
Publisher
Publisher gửi tin nhắn đến kênh mychannel
.
Giải thích:
jedis.publish(channel, message)
gửi tin nhắn đến kênh được chỉ định.Publisher không cần biết có bao nhiêu subscriber đang lắng nghe.
3. Cách chạy
Khởi động Redis server:
Nếu bạn dùng máy local, chạy lệnh:
Đảm bảo Redis chạy trên
localhost:6379
(hoặc cấu hình lại trong code nếu khác).
Chạy Subscriber:
Chạy lớp
RedisSubscriber
trước. Bạn sẽ thấy output:
Chạy Publisher:
Chạy lớp
RedisPublisher
. Output của Publisher:Ở cửa sổ Subscriber, bạn sẽ thấy:
4. Mở rộng: Đăng ký nhiều kênh hoặc dùng mẫu kênh
Nếu muốn lắng nghe nhiều kênh hoặc dùng mẫu kênh (pattern), bạn có thể sửa code Subscriber như sau:
Publisher gửi tin nhắn đến kênh news.sport
:
Kết quả ở Subscriber:
5. Lưu ý
Blocking: Phương thức
subscribe
vàpsubscribe
chặn luồng hiện tại. Nếu bạn cần xử lý đồng thời, hãy chạy Subscriber trong một thread riêng.Xử lý lỗi: Đảm bảo xử lý ngoại lệ khi kết nối Redis bị gián đoạn.
Hiệu suất: Jedis không tự động quản lý pool kết nối trong ví dụ đơn giản này. Trong ứng dụng thực tế, dùng
JedisPool
để quản lý kết nối hiệu quả hơn.Không lưu trữ tin nhắn: Như đã đề cập, Redis Pub/Sub không lưu tin nhắn, nên nếu Subscriber không hoạt động, nó sẽ bỏ lỡ tin nhắn.
6. Ví dụ với JedisPool (thực tế hơn)
Dùng JedisPool
để quản lý kết nối trong môi trường sản xuất:
Subscriber với JedisPool:
Last updated