Kafka Fundamental - Bài 4: Consumers, Deserialization, Consumer Groups & Consumer Offsets

0 0 0

Người đăng: Đức Phúc

Theo Viblo Asia

Xin chào, lại là mình - Đức Phúc, anh chàng hơn 6 năm trong nghề vẫn nghèo technical nhưng thích viết Blog để chia sẻ kiến thức bản thân học được trong quá trình “cơm áo gạo tiền” đây. Các bạn có thể theo dõi mình thêm qua một số nền tảng bên dưới nhé:

Ở bài trước, chúng ta đã tìm hiểu về cách mà Message được gửi đến Kafka. Ở bài này, chúng ta sẽ tìm hiểu về cách mà Kafka đọc Message. Để làm được điều đó, chúng ta sẽ sử dụng Consumer

1. Consumers

Điều đầu tiên phải nhắc đến, là Kafka Consumers được xem là “Pull Model”, nghĩa là nó sẽ yêu cầu nhận dữ liệu từ Kafka Brokers, từ đó nhận được dữ liệu, thay vì Kafka Brokers gửi dữ liệu đến Consumers image.png

Ở đây, chúng ta có 1 ví dụ cơ bản. Topic A sẽ có 3 Partions là A1, A2 và A3. Ta cũng có 2 Consumers. Như các bạn thấy, Consumers đầu tiên sẽ đọc từ 2 Partitions A1 và A2. Hiển nhiên, Consumer còn lại sẽ đọc từ A3. Việc đọc dữ liệu được thực hiện tuần tự cho mỗi Partition, tức là sẽ đọc từ Offset thấp đến Offset cao hơn. Sẽ không có bất kì thứ tự nào giữa các Partition, điều này chúng ta đã nhắc đến ở bài học trước

2. Consumer Deserializer

Ở bài trước, chúng ta đã biết Message sẽ được gửi đến dưới dạng Byte. Vậy thì khi đọc những Message này, chúng sẽ cần được chuyển đổi lại sang dữ liệu ban đầu. Quá trình này được gọi là Deserializer image.png

Ở hình ảnh minh hoạ trên, ta đã thấy rằng Message sẽ được chuyển đổi từ dạng Byte về dạng ban đầu của nó. Tất nhiên, Kafka biết cách để chọn kiểu dữ liệu phù hợp cho việc chuyển đổi

Để đảm bảo cho việc đó, thì trong vòng đời của một Topic, nghĩa là ngay từ khi Topic được khởi tạo, bạn tuyệt đối không được thay đổi kiểu dữ liệu được gửi bởi Producers. Nếu không tuân thủ điều này, chúng ta sẽ phá vỡ cách Consumers chuyển đổi dữ liệu

Trong trường hợp bạn muốn thay đổi kiểu dữ liệu của Topic, bạn sẽ cần tạo 1 Topic mới. Lúc này, Consumer sẽ tự động điều chỉnh, để có thể đọc được dữ liệu chính xác

3. Consumer Groups

Okay, ta đã nói về Group. Vậy thì khi muốn mở rộng (scale), chúng ta sẽ cần nhiều Consumer trên hệ thống. Những Consumer này có thể được gộp lại với nhau, và ta gọi mỗi nhóm như vậy là Consumer Group

Những Consumer trong cùng 1 Group sẽ chia nhau để có thể đọc được hết dữ liệu từ tất cả các Partitions. Mỗi Consumer sẽ đọc dữ liệu từ những Partition khác nhau

Bây giờ, ta hãy xem xét một số ví dụ như sau:

3.1. Số Consumer < Số Partition

image.png Đây là trường hợp cơ bản nhất, lúc này, các Consumer sẽ chia đều nhau để mỗi Consumer có thể đọc Message từ một Partition.

3.3. Số Consumer > Số Partition (Ít xảy ra)

image.png Trong trường hợp này, vì số Consumer đã đủ để đọc được dữ liệu từ Partition, những Consumer còn lại sẽ ở trạng thái INACTIVE. Nghĩa là nó sẽ không được sử dụng để đọc dữ liệu từ Partition

3.4. Nhiều Consumer Group cùng đọc dữ liệu trên một Topic

image.png Kết hợp những trường hợp ở trên, ta có thể nhân bản nó khi có nhiều Consumer Group cùng đọc dữ liệu trên một Topic. Như ví dụ minh hoạ, ta có thể thấy:

  • Consumer-groups-1
    • Consumer 1 → Partition 1 và Partition 2
    • Consumer 2 → Partition 3
  • Consumer-groups-2
    • Consumer 1 → Partition 1
    • Consumer 2 → Partition 2
    • Consumer 3 → Partition 3
  • Consumer-groups-3: Consumer 1 → Partition 1, Partition 2 vaf Partition 3

Như vậy, dù cho có nhiều Consumer Groups đi nữa, thì trong mỗi Consumer Group, nó luôn tuân thủ rằng, mỗi Consumer sẽ đọc dữ liệu từ những Partition riêng biệt. Không có bất kì 1 Partition nào được đọc từ 2 Consumer khác nhau trong cùng 1 Group

4. Consumer Offsets

Khái niệm tiếp theo mà ta nhắc đến, ta Consumer Offset. Với mỗi Consumer, chúng sẽ tự động ghi lại Offset mà chúng đã đọc từ Topic, điều này sẽ giúp chúng đánh dấu được mình đã đọc được đến Offset nào trong Topic

Những Committed Offset này sẽ được lưu ở những Topic đặc biệt, và được đặt tên là __consumer_offsets. Hai dấu gạch dưới đầu tiên biểu thị đây là Internal Topic (Kafka tự quản lý nó, không phải để người dùng đọc/ghi trực tiếp.) image.png Ở hình minh hoạ, ta có thể thấy, Commited Offset lúc này là 101. Như vậy, ở lần đọc tiếp theo, Consumer sẽ biết rằng nó sẽ cần đọc từ Offset 102

Khi Consumer nhận/xử lý những Message, nó sẽ tiến hành gửi Offset này định kỳ. Tuy nhiên, bạn cần nhớ rằng, Kafka Broker mới là thứ đóng vai trò ghi những Offset này vào Topic __consumer_offsets, không phải Consumer Group

Vậy thì, khi nào Consumer tiến hành commit Offset? Thông thường, ta sẽ có 3 phương án để lựa chọn

Phương án Ưu điểm Nhược điểm Trường hợp sử dụng
At-most-one Commit ngay khi Consumer nhận được Message ⇒ Nhanh, không cần đợi quy trình xử lý Message phía sau Vì không cần đợi quy trình xử lý hoàn thành ⇒ Nếu quy trình xử lý lỗi, mà Offset đã được commit trước đó ⇒ Mất dữ liệu vì không thể đọc lại Cần xử lý nhanh, chấp nhận mất một số dữ liệu
At-least-one Commit sau khi quá trình xử lý Message hoàn tất ⇒ Tránh rủi ro mất dữ liệu từ At-most-one Nếu xử lý xong mà chưa kịp commit ⇒ retry lại ⇒ có thể xử lý trùng message. Cần đảm bảo không bỏ sót dữ liệu, nhưng chấp nhận được sự trùng lặp
Exactly-one Hỗ trợ commit Message qua Kafka Transaction API, Kafka Stream. Tránh được cả 2 rủi ro về mất dữ liệu (At-most-one) và trùng lặp dữ liệu (At-least-once) Cấu hình phức tạp hơn, cần nắm thêm kiến thức về Kafka Stream, Kafka Transaction. Tốn nhiều tài nguyên hơn, hiệu suất thấp hơn Cần chính xác tuyệt đối, không thừa và không thiếu về dữ liệu

Như vậy, với mỗi phương án, ta đều có Ưu và Nhược điểm riêng. Ta sẽ tìm hiểu sâu hơn về những kiến thức này sau. Nhưng trước hết, các bạn có thể nắm sơ lược về nội dung này thông qua bảng trên nhé

Còn bây giờ thì nghỉ ngơi thôi, bài này đã dài rồi. Hẹn gặp lại các bạn ở những bài viết tiếp theo nhé!

Một lần nữa, đừng quên connect với mình để cùng trao đổi nhé

Bình luận

Bài viết tương tự

- vừa được xem lúc

Quá trình de/serialization trong java thực sự diễn ra như thế nào?

Giới thiệu. .

0 0 37

- vừa được xem lúc

Nhập môn .NET deserialization

Tản mạn. Dạo gần đây thì dân tình xôn xao về những bug hằng trăm nghìn $ của Microsoft như trên Microsoft Mail Exchange Server, Sharepoint hay các công ty nổi tiếng khác như Solarwind.

0 0 96

- vừa được xem lúc

Phân tích CVE-2021-42392 H2 Database

Lỗ hổng này là một lỗ hổng liên quan đến Deserialization. Nó khá giống với Log4j, nhưng impact thì thấp hơn rất nhiều. Target là H2 Database version < 2.0.

0 0 24

- vừa được xem lúc

Phân tích lỗ hổng Deserialization trong Bitbucket CVE-2022-26133

Về desialization là gì thì anh em có thể tham khảo thêm ở đây. Trên Jira của Atlassian đã mô tả về lỗi như sau:.

0 0 34

- vừa được xem lúc

Phân tích gadget CommonsCollections1 trong ysoserial

Để khai thác lỗ hổng Deserialization, ngoài việc phải kiểm soát được giá trị đầu vào để đưa vào hàm thực hiện deserialize, ta cũng cần phải có một Object mà khi nó được deserialize, nó sẽ gọi tới một

0 0 30

- vừa được xem lúc

Phân tích CVE-2017-3066 - AMF Deserialization trong Adobe ColdFusion

1. Giới thiệu.

0 0 29