1. Giới Thiệu
Kafka là một hệ thống phân phối mạnh mẽ, trong đó mỗi khi chúng ta gọi hàm poll()
, nó sẽ trả về các thông điệp đã được ghi vào Kafka mà chưa được các consumer trong nhóm đọc. Một điểm nổi bật của Kafka là nó không theo dõi xác nhận từ các consumer theo cách mà nhiều hệ thống hàng đợi JMS thực hiện. Thay vào đó, Kafka cho phép các consumer tự theo dõi vị trí của mình (offset) trong từng partition.
Hành động cập nhật vị trí hiện tại trong một partition được gọi là commit offset. Khác với các hệ thống hàng đợi thông thường, Kafka không commit từng message riêng lẻ mà chỉ commit offset của message cuối cùng được xử lý thành công trong một partition và coi như tất cả các message trước đó cũng đã được xử lý.
2. Cách Commit Offset trong Kafka
Khi một consumer thực hiện commit, nó sẽ gửi một message đến Kafka nhằm cập nhật một topic đặc biệt mang tên consumer_offsets
với offset đã được commit cho mỗi partition. Nếu một consumer gặp sự cố hoặc có một consumer mới tham gia vào nhóm, điều này sẽ kích hoạt quá trình rebalance. Sau khi rebalance, các consumer mới sẽ được gán lại với các partition khác và cần phải đọc offset đã commit gần nhất của từng partition để tiếp tục xử lý.
3. Các Tình Huống Gợi Ý Về Commit Offset
Nếu committed offset nhỏ hơn offset của message cuối cùng đã xử lý, consumer sẽ xử lý lại các message giữa offset cuối cùng và committed offset. Trong khi đó, nếu committed offset lớn hơn offset cuối cùng được thực tế xử lý, tất cả các message giữa hai offset này sẽ bị bỏ sót. Điều này có thể gây ảnh hưởng lớn đến ứng dụng của bạn.
4. Commit Offset Tự Động
Cách đơn giản để commit offset là sử dụng tính năng tự động. Khi thiết lập enable.auto.commit=true
, consumer sẽ tự động commit offset mới nhất được trả về từ poll()
mỗi 5 giây, giá trị này có thể điều chỉnh qua auto.commit.interval.ms
. Tuy nhiên, việc sử dụng commit tự động cần được cân nhắc kỹ lưỡng để tránh việc xử lý trùng lặp khi có sự cố xảy ra.
5. Commit Offset Thủ Công
Hầu hết các nhà phát triển thường lựa chọn commit offset thủ công để chính xác hơn trong việc tránh mất mát message. Khi thiết lập enable.auto.commit=false
, developer có thể gọi phương thức commitSync()
để commit offset mới nhất. Tuy nhiên, cần lưu ý rằng nếu gọi commitSync()
trước khi hoàn tất xử lý tất cả bản ghi, có thể sẽ bị bỏ lỡ một số message.
6. Commit Không Đồng Bộ
Để cải thiện hiệu suất, bạn có thể sử dụng commitAsync()
, cho phép gửi yêu cầu commit mà không cần chờ phản hồi từ broker. Dù vậy, phương thức này có một nhược điểm là không thử lại nếu có lỗi xảy ra, do đó cần cẩn trọng với thứ tự commit chính xác để tránh xử lý nhiều lần message.
7. Thử Lại Commits Không Đồng Bộ
Để đảm bảo thứ tự commit khi thử lại, bạn có thể sử dụng một số thứ tự tăng dần. Khi gửi yêu cầu commit, bạn có thể thêm số thứ tự vào callback của commitAsync()
. Nếu số thứ tự trong callback cao hơn, bạn không thử lại commit đó nữa.
8. Kết Hợp Commit Sync và Async
Một giải pháp phổ biến là kết hợp commitAsync()
với commitSync()
trước khi dừng application. Khi hoạt động bình thường, xử lý với commitAsync()
sẽ nhanh hơn, nhưng khi dừng, sử dụng commitSync()
để đảm bảo commit này hoàn thành thành công.
9. Kết Nối và Thảo Luận
Nếu bạn muốn trao đổi thêm về bài viết này, hãy kết nối với mình qua:
Mong được gặp gỡ và chia sẻ kinh nghiệm!
source: viblo