Series Redis Thực chiến | Bài 4: Redis Pub/Sub - Đài phát thanh "siêu tốc" cho Microservices
Chào anh em! Giả sử hệ thống bán vé của chúng ta có yêu cầu: Khi một đơn hàng (Order) được thanh toán thành công, hệ thống cần gửi thông báo cho 3 bên:
- Module AFC (Trạm): Để chuẩn bị đồng bộ dữ liệu vé.
- Module Marketing: Để cộng điểm thưởng cho khách.
- Module Realtime Dashboard: Để cập nhật bảng xếp hạng doanh thu theo thời gian thực.
Nếu viết theo kiểu tuần tự, bạn phải gọi lần lượt từng hàm, tốn cực nhiều thời gian. Nếu viết theo kiểu Event-Driven (Bài 3 series Architecture), bạn cần một Message Broker nặng đô như RabbitMQ hay Kafka. Nhưng nếu dự án của bạn ở quy mô vừa phải, cần sự đơn giản và tốc độ "tức thì", Redis Pub/Sub là lựa chọn hoàn hảo.
1. Bản chất của Pub/Sub: Mô hình "Phát - Thu"
Khác với Redis Data Structure (lưu trữ key-value trên RAM), Pub/Sub là một Cơ chế truyền tin nhắn.
- Publisher (Người phát): Chỉ gửi tin nhắn vào một "Kênh" (Channel). Nó không cần biết có ai đang nghe hay không, cũng không cần biết người nhận là ai.
- Subscriber (Người thu): Đăng ký lắng nghe một hoặc nhiều kênh. Khi có tin nhắn đến, nó sẽ nhận được ngay lập tức.
Redis không lưu trữ tin nhắn này. Nếu một Subscriber đang "off", nó sẽ không nhận được tin nhắn đó. Đây là điểm khác biệt cốt lõi so với Message Queue (như Kafka/RabbitMQ).
2. Thực hành: Code Pub/Sub với Redis
Bước 1: Publisher (Phát tín hiệu)
Tại OrderController, sau khi thanh toán thành công:
use Illuminate\Support\Facades\Redis;
public function checkout()
{
// ... logic thanh toán ...
$orderData = ['order_id' => 123, 'total' => 50000];
// Publish dữ liệu vào kênh có tên 'order_processed'
Redis::publish('order_processed', json_encode($orderData));
return response()->json(['status' => 'success']);
}
Bước 2: Subscriber (Lắng nghe) Subscriber thường không chạy trong luồng HTTP (web), mà nó phải chạy dưới dạng một Worker (Process chạy ngầm) trên server. Anh em tạo một Artisan Command:
php artisan make:command SubscribeOrder
Trong file SubscribeOrder.php:
public function handle()
{
$this->info("Đang lắng nghe kênh 'order_processed'...");
Redis::subscribe(['order_processed'], function ($message) {
$data = json_decode($message, true);
$this->info("Đã nhận tin: Đơn hàng " . $data['order_id']);
// Tại đây bạn có thể gọi Module Marketing, AFC...
// để xử lý công việc của họ một cách độc lập
});
}
3. Khi nào dùng Pub/Sub và khi nào dùng Redis Streams?
Anh em cần đặc biệt lưu ý:
- Dùng Pub/Sub khi: Cần sự kiện "tức thì", không quan trọng nếu tin nhắn bị mất trong trường hợp Subscriber đang tắt máy (ví dụ: thông báo realtime cho người dùng, làm dashboard báo cáo, cập nhật UI).
- Dùng Redis Streams (hoặc Message Queue): Nếu tin nhắn đó là "sống còn" (ví dụ: giao dịch tài chính, tạo vé), cần đảm bảo 100% tin nhắn phải được xử lý dù Subscriber có bị crash. Redis Streams là một cấu trúc dữ liệu xịn hơn của Redis giúp lưu trữ tin nhắn bền vững, hỗ trợ đọc lại dữ liệu cũ.
Tổng kết Bài 4
Redis Pub/Sub là một công cụ cực kỳ nhẹ và nhanh để xây dựng hệ thống giao tiếp giữa các thành phần hoặc các Microservices. Nó giúp anh em tách rời (decouple) logic cực tốt: Module Order chỉ cần bắn tin, các module khác tự lo liệu phần việc của mình.
Đã đi qua 4 bài về các tính năng "ăn tiền" nhất của Redis. Bài 5 sẽ là Redis Streams, đây là công nghệ cao cấp nhất của Redis hiện nay, biến Redis thành một Message Broker thực thụ ngang hàng với Kafka. Bạn có muốn chúng ta chốt series bằng kiến thức "trùm cuối" này không?
All rights reserved