DDevArchive
Đăng nhập

Message broker cơ bản: RabbitMQ và Kafka

Khi một thao tác kéo theo nhiều việc phụ (gửi email, cập nhật cache, tính toán thống kê), làm đồng bộ sẽ làm chậm và dễ hỏng. Message broker tách việc phụ ra: gửi đi rồi thôi, ai đó sẽ xử lý.

Bài toán: đăng ký mà không gửi email trực tiếp

// File: sync.js
// Đăng ký xong, gửi email NGAY trong request
app.post("/api/auth/register", async (req, res) => {
  const user = await createUser(req.body);
  await mailer.sendWelcome(user.email);   // chậm 2-5 giây!
  await stats.increment();                // thêm nữa
  res.status(201).json(user);
});

// Email service sập -> cả đăng ký cũng lỗi theo
// File: async.js
app.post("/api/auth/register", async (req, res) => {
  const user = await createUser(req.body);
  await queue.publish("user.registered", { userId: user.id });
  res.status(201).json(user);     // trả về ngay
});

// Worker riêng lắng nghe queue và làm việc phụ
queue.consume("user.registered", async ({ userId }) => {
  const user = await getUser(userId);
  await mailer.sendWelcome(user.email);
  await stats.increment();
});
💡 Khi nào cần broker

Việc phụ (side effect) chậm, có thể thất bại, không cần trả về tức thì: email, push notification, xử lý ảnh, tính toán thống kê. Nếu chỉ là “gọi hàm thêm” nhanh, đừng thêm độ phức tạp.

RabbitMQ vs Kafka

Đặc điểmRabbitMQKafka
Mô hìnhQueue, routing phức tạpLog phân tán, replay được
Cách tiêu thụMột consumer nhận mỗi messageNhiều consumer group độc lập
Lưu trữXoá sau khi xử lýGiữ lại, replay được
Phù hợpTask/job, gửi email, công việc nềnEvent streaming, log, data pipeline
Độ phức tạpDễ hơnKhó hơn, nặng hơn

At-least-once và idempotency

Broker thường gửi “ít nhất một lần” — message có thể bị xử lý trùng. Nên consumer phải idempotent: xử lý trùng không gây hậu quả (dùng unique key, so trạng thái trước khi ghi).

Dead letter queue

Message xử lý thất bại nhiều lần sẽ bị đẩy sang dead letter queue (DLQ) — nơi để con người xem xét. Đừng để message hỏng chặn cả hàng đợi.

❓ Worker xử lý message gửi email. Nhận tin "user.registered" lần hai vì broker gửi lại. Nên làm gì?

  • Nhận biết việc phụ nên tách bất đồng bộ
  • Chọn RabbitMQ hay Kafka theo bài toán
  • Viết consumer idempotent
  • Cấu hình dead letter queue