3 Giai Đoạn Chính Để Đảm Bảo Tin Nhắn Kafka Không Bị Mất

Tìm hiểu ba giai đoạn quan trọng trong quá trình xử lý tin nhắn Kafka để tránh mất tin nhắn và đảm bảo độ tin cậy của hệ thống

Kafka và câu chuyện mất tin nhắn – Hiểu đúng và xử lý hiệu quả

Kafka được phát triển ban đầu bởi LinkedIn với mục đích xử lý lượng log khổng lồ. Nó hoạt động như một hệ thống phân tán giúp ghi lại các sự kiện theo thời gian thực. Tuy nhiên, như mọi hệ thống phức tạp khác, Kafka cũng có thể đối mặt với tình trạng mất tin nhắn – một vấn đề mà bất kỳ ai triển khai đều phải hiểu rõ để hạn chế rủi ro.

Kafka được sử dụng để làm gì?

Ban đầu Kafka chỉ dùng cho việc ghi log – đơn giản, không yêu cầu độ tin cậy cao. Nhưng ngày nay, Kafka đã trở thành một nền tảng mạnh mẽ cho:

  • Giao tiếp giữa các microservices (event-driven architecture)
  • Đồng bộ dữ liệu giữa các hệ thống
  • Phân tích dữ liệu thời gian thực

Dù vậy, việc mất message hoặc trùng lặp message vẫn có thể xảy ra. Nguyên nhân đến từ việc hệ thống phân tán vốn khó kiểm soát toàn diện.

3 Giai đoạn chính của vòng đời một message trong Kafka

Để hiểu vì sao message bị mất, bạn cần nắm rõ 3 giai đoạn chính từ lúc message được gửi đến khi nó được xử lý xong:

1. Giai đoạn gửi (Producer)

Ở giai đoạn đầu, producer sẽ tạo và gửi message đến broker qua mạng. Các vấn đề có thể xảy ra:

  • Kết nối mạng bị ngắt
  • Producer chưa nhận được phản hồi đã retry => tạo duplicate
  producer.send({
    topic: "order-topic",
    message: JSON.stringify({ orderId: 123, status: "new" })
  });
  

2. Giai đoạn lưu trữ (Broker)

Broker nhận và ghi message vào log. Các vấn đề ở đây:

  • Replication chưa hoàn tất mà broker gặp sự cố
  • Retention time quá ngắn khiến message bị xóa sớm
  // Giao tiếp giữa các broker:
  Leader Broker ghi log trước
  Follower Broker đồng bộ sau để đảm bảo an toàn dữ liệu
  

3. Giai đoạn tiêu thụ (Consumer)

Consumer đọc và xử lý message. Rủi ro có thể gồm:

  • Consumer crash sau khi xử lý nhưng trước khi commit offset
  • Xử lý lỗi dẫn đến skip message
  const message = await consumer.read();
  await process(message);
  await consumer.commit();
  

Làm sao để hạn chế mất message?

  • Sử dụng cơ chế acks=all ở producer để đảm bảo message ghi đủ replicas
  • Đặt min.insync.replicas để yêu cầu số lượng broker đồng bộ
  • Consumer cần xử lý idempotent để tránh duplicate khi retry
  • Sử dụng hệ thống monitoring (Prometheus, Grafana) để theo dõi cluster

Thái độ & nhận thức

Không có gì là tuyệt đối – kể cả trong công nghệ. Dù bạn có hệ thống tối ưu đến đâu, rủi ro vẫn tồn tại. Quan trọng là bạn nhận thức được điều đó và chuẩn bị trước để phản ứng nhanh chóng khi có sự cố. Việc hiểu rõ từng giai đoạn của message giúp bạn xử lý bài bản và có hệ thống.

Hãy nhớ: Thành công của một hệ thống Kafka không chỉ đến từ hiệu suất, mà còn từ sự cẩn trọng trong thiết kế và vận hành.

Xin chào! Mình là BaoTrongIT – một lập trình viên đam mê chia sẻ kiến thức lập trình, đặc biệt là về JavaScript, Node.js, NestJS, và các công nghệ backend/frontend hiện đại. Trên blog này, mình thường xuyên đăng tải các bài viết thủ thuật, kinh nghiệm thực chiến, ví dụ minh họa dễ hiểu, giúp bạn tiếp cận và hiểu sâu các khái niệm tưởng như phức tạp trong lập trình.