Kafka Consumer
Last updated
Last updated
Kafka Consumer là một client đọc dữ liệu từ các topic trong Kafka cluster. Mỗi consumer thuộc về một consumer group nhất định, và các consumer trong cùng nhóm sẽ chia sẻ việc đọc dữ liệu từ các partition của topic.
Pull-based: Consumer chủ động kéo dữ liệu từ broker
Có thể đọc dữ liệu theo thứ tự (ordered) trong mỗi partition
Hỗ trợ xử lý song song thông qua consumer groups
Cơ chế commit offset để theo dõi vị trí đã đọc
Sau khi đọc 1 message thì consumer không xoá message đó khỏi topic
Một tập hợp các consumer cùng làm việc để tiêu thụ dữ liệu từ một hoặc nhiều topic. Mỗi partition của topic sẽ được gán cho duy nhất một consumer trong nhóm.
Consumer Group là cơ chế load balancing: gọi là "balancing" (cân bằng tải) vì cơ chế này tự động phân phối partition cho các consumer trong nhóm sao cho tải xử lý được chia đều nhất có thể, đảm bảo không có consumer nào bị quá tải hoặc "nhàn rỗi".
Quá trình phân phối các partition cho các consumer trong nhóm, có thể thực hiện thông qua:
RangeAssignor (mặc định)
Phân phối partition theo khoảng (range).
Sắp xếp partition và consumer theo thứ tự, rồi chia đều thành các khoảng.
RoundRobinAssignor
Phân phối luân phiên (vòng tròn) tất cả partition của tất cả topic mà consumer subscribe.
Yêu cầu: Tất cả consumer trong nhóm phải subscribe cùng danh sách topic.
Ví dụ
Tổng số partition cần phân phối: 3 (A) + 2 (B) = 5 partitions.
C1 nhận: A-P0, A-P2, B-P0
C2 nhận: A-P1, B-P1
→ Tải được cân bằng giữa 2 consumer.
StickyAssignor
Kết hợp RoundRobin + Ưu tiên giữ partition cũ khi rebalance.
Giảm thiểu việc di chuyển partition giữa các consumer khi có thay đổi.
ví dụ:
C1: P0, P2
C2: P1, P3
→ Mỗi consumer giữ 2 partitions (cân bằng hoàn hảo).
Khi C3 join nhóm
Tổng partitions: 4 (P0, P1, P2, P3)
Tổng consumers: 3 (C1, C2, C3)
→ Lý tưởng: Mỗi consumer giữ 1 partition, 1 partition dư sẽ được gán thêm cho 1 consumer.
Di chuyển 2 partitions (P2, P3) từ C1 và C2 sang C3 để cân bằng:
P2 (từ C1) → C3.
P3 (từ C2) → C3.
Giữ nguyên partition đang được gán cho C1 và C2:
C1 giữ P0 (không động đến).
C2 giữ P1 (không động đến).
Kết quả cuối cùng:
C1: P0
C2: P1
C3: P2, P3
Lý do chỉ P2 và P3 bị di chuyển:
StickyAssignor không muốn động đến P0 và P1 (đang được C1 và C2 xử lý ổn định).
Việc di chuyển P2 và P3 là đủ để đạt cân bằng (C3 nhận 2 partitions, C1 và C2 nhận 1 partition).
Custom Assignor (tự định nghĩa)
Quá trình Consumer Rebalance xảy ra khi
Consumer mới tham gia nhóm
Consumer rời khỏi nhóm (shutdown hoặc crash)
Topic được subscribe có partition mới được thêm
💡Trong trường hợp ta tạo 1 consumer mà không chỉ định consumer group name thì consumer sẽ tự động tạo 1 random consumer group và sẽ chịu trách nhiệm nhận dữ liệu từ tất cả các partition của Topic nó subsribe.💡Nếu ta tạo 1 consumer với consumer group name, consumer sẽ join group. Lúc này nó sẽ nhận dữ liệu từ tất cả partition. Sau khi có consumer thứ 2 join, một cơ chế rebalance sẽ được kích hoạt. Tương tự những consumer tiếp theo tham gia cũng sẽ thế.
💡Có trường hợp nào Partition được gán cho nhiều consumer không?
Nếu xét trong 1 consumer group thì 1 partition chỉ có thể gán cho duy nhất 1 consumer. Điều này dẫn tới nếu số consumer nhiều hơn số partition thì sẽ có consumer không nhận dữ liệu từ partition nào.
→ Việc thêm consumer thừa sẽ gây tốn tài nguyên nhưng sẽ có tác dụng trong các hệ thống cần High Availability thì có consumer thừa sẽ thay thế nếu có consumer gặp vấn đề.
💡Kafka Consumer sử dụng mô hình Pull hay Push? Ưu điểm?
Pull-based: Consumer chủ động kéo dữ liệu từ broker.
Ưu điểm:
Consumer kiểm soát tốc độ xử lý (tránh quá tải).
Broker không cần lưu trữ trạng thái của consumer.
💡Consumer Rebalance là gì? Khi nào nó xảy ra?
Rebalance là quá trình phân phối lại partition giữa các consumer trong nhóm.
Xảy ra khi:
Consumer mới tham gia hoặc rời nhóm.
Topic thêm partition mới.
Consumer bị crash hoặc mất kết nối (timeout).
Lưu ý: Rebalance có thể gây gián đoạn xử lý (cần tối ưu bằng StickyAssignor
).
💡Nếu consumer xử lý message bị lỗi, làm thế nào để tránh mất dữ liệu?
Chỉ commit offset sau khi xử lý thành công
Pattern khác: Ghi message lỗi vào topic riêng ("dead-letter queue") để xử lý sau.
Tắt auto-commit (.commit=false
).