Bài 3: Định tuyến dữ liệu (Message Keys) và Nhóm tiêu thụ (Consumer Group)
1. Message Key: Lời giải cho bài toán thứ tự
Như đã đề cập ở Bài 2, Kafka chỉ đảm bảo thứ tự tin nhắn trong cùng một Partition. Khi một ứng dụng gửi tin nhắn (Producer) vào Kafka, cấu trúc thực sự của tin nhắn là một cặp Key-Value (Khóa - Giá trị), trong đó phần Key là tùy chọn.
Cách Producer quyết định tin nhắn sẽ rơi vào Partition nào phụ thuộc hoàn toàn vào việc bạn có truyền Key hay không:
- Trường hợp 1: Không có Key (Key = null)
Producer sẽ phân phối tin nhắn theo chiến lược Round-robin (chia bài). Tin nhắn 1 vào Partition 0, tin nhắn 2 vào Partition 1, tin nhắn 3 vào Partition 2... Hệ quả: Tốc độ ghi cực nhanh và tải được cân bằng hoàn hảo, nhưng thứ tự của các tin nhắn có liên quan đến nhau sẽ bị phá vỡ.
- Trường hợp 2: Có Key (Key != null)
Producer sẽ mang Key đi băm (hashing). Công thức cơ bản của Kafka là Hash(Key) % Số lượng Partition.
Hệ quả: Những tin nhắn có cùng một Key sẽ luôn luôn sinh ra cùng một giá trị hash, do đó luôn rơi vào cùng một Partition.
Ví dụ thực tế: Trong một hệ thống thu phí tự động (AFC), bạn cần xử lý các sự kiện quẹt thẻ vào/ra của cùng một mã vé ticket_12345. Bạn chỉ cần đặt Message Key là ticket_12345. Toàn bộ giao dịch của chiếc vé này sẽ đi vào một Partition duy nhất. Consumer đọc Partition đó sẽ nhận được chuỗi trạng thái vé theo đúng thứ tự thời gian thực tế, loại bỏ hoàn toàn rủi ro xử lý lệch pha.
2. Consumer Group: Sức mạnh của sự phân chia công việc
Nếu một Topic có hàng triệu tin nhắn đổ về mỗi giây, một ứng dụng Consumer duy nhất sẽ không thể đọc kịp. Kafka cho phép bạn chạy nhiều bản sao của ứng dụng Consumer đó (ví dụ: chạy trên nhiều server khác nhau để tăng tốc) và gom chúng lại thành một Consumer Group (được định danh bằng một tham số là group.id).
Quy tắc vàng của Consumer Group: Trong cùng một Consumer Group, một Partition chỉ được đọc bởi tối đa MỘT Consumer tại một thời điểm.
Quy tắc này nhằm đảm bảo không có hai Consumer nào "tranh nhau" đọc một tin nhắn dẫn đến việc xử lý đúp (nhân đôi giao dịch). Hãy xem cách Kafka phân bổ công việc dựa trên số lượng Partition và Consumer:
| Kịch bản (Topic có 4 Partitions) | Phân bổ công việc | Đánh giá hiệu năng |
|---|---|---|
| 2 Consumers | Mỗi Consumer tự động gánh 2 Partitions. | Hoạt động bình thường. |
| 4 Consumers | Mỗi Consumer đọc đúng 1 Partition. | Tối ưu nhất. Tải được chia đều tối đa, khai thác hết công suất. |
| 5 Consumers | 4 Consumer đọc, 1 Consumer "ngồi chơi". | Consumer dư thừa làm phương án dự phòng (Failover). Nếu 1 máy chết, nó lập tức nhảy vào thay thế. |
Lưu ý quan trọng: Nếu bạn có hai ứng dụng hoàn toàn khác nhau (ví dụ: Dịch vụ Giao hàng và Dịch vụ Thống kê) cùng muốn đọc một Topic, bạn phải đặt chúng vào hai Consumer Group khác nhau. Khi đó, cả hai hệ thống sẽ đọc lại từ đầu toàn bộ dữ liệu một cách độc lập mà không ảnh hưởng tới nhau.
All rights reserved