Gejala
Saat client consumer menggunakan strategi penugasan partisi StickyAssignor, beberapa consumer thread mengonsumsi partisi yang sama, sehingga menyebabkan pemrosesan pesan duplikat atau tidak sesuai urutan.
Penyebab
Ini merupakan bug yang telah diketahui (KAFKA-7026 / KIP-341) pada versi client Apache Kafka sebelum 2.3. StickyAssignor tidak melakukan deduplikasi terhadap penugasan partisi ketika sebuah consumer kembali bergabung ke kelompok dengan data penugasan yang sudah kedaluwarsa.
Skenario berikut mereproduksi masalah tersebut:
Consumer C1 bergabung ke kelompok consumer sebagai leader dan ditugaskan ke partisi
test-0.Consumer C2 bergabung ke kelompok yang sama. C1 tetap mempertahankan
test-0, sedangkan C2 tidak menerima partisi apa pun.C1 menjadi tidak responsif (misalnya, karena jeda GC yang lama). C2 kemudian menjadi leader baru dan mengambil alih
test-0.C1 pulih dan kembali bergabung ke kelompok dengan penugasan lamanya (
test-0). Baik C1 maupun C2 melaporkantest-0sebagai penugasan yang sedang mereka miliki selama proses rebalancing.StickyAssignortidak memeriksa duplikat, sehingga menugaskantest-0ke kedua consumer tersebut.
Solusi
Opsi 1: Upgrade client Kafka ke versi 2.3 atau lebih baru (direkomendasikan)
Bug ini telah diperbaiki di Apache Kafka 2.3. Lakukan upgrade dependensi client Kafka dalam aplikasi Anda:
<!-- Contoh Maven -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.3.0</version> <!-- atau lebih baru -->
</dependency>Opsi 2: Beralih ke strategi penugasan partisi yang berbeda
Jika Anda belum dapat segera melakukan upgrade, beralihlah ke strategi penugasan partisi yang berbeda. Tabel berikut menjelaskan strategi yang tersedia:
| Strategi | Nama kelas | Deskripsi | Trade-off |
|---|---|---|---|
| Range (default) | RangeAssignor | Mendistribusikan partisi setiap topik secara merata ke seluruh consumer. | Sederhana dan prediktabel. Dapat menghasilkan distribusi yang tidak merata ketika jumlah partisi bukan kelipatan dari jumlah consumer. |
| Round-robin | RoundRobinAssignor | Menugaskan partisi satu per satu secara round-robin ke seluruh consumer. | Lebih seimbang dibandingkan Range. Dapat menyebabkan lebih banyak perpindahan partisi selama rebalancing. |
| Cooperative sticky | CooperativeStickyAssignor | Menggunakan logika penyeimbangan yang sama seperti StickyAssignor, tetapi menggunakan protokol rebalancing kooperatif untuk menghindari rebalancing stop-the-world. | Meminimalkan perpindahan partisi dan menghindari bug penugasan duplikat. Memerlukan migrasi dua langkah dari assignor berbasis eager protocol. |
Untuk mengubah strategi, atur properti konfigurasi consumer partition.assignment.strategy:
props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,
"org.apache.kafka.clients.consumer.RoundRobinAssignor");Migrasi ke CooperativeStickyAssignor
Untuk bermigrasi dari StickyAssignor ke CooperativeStickyAssignor pada kelompok consumer yang sedang berjalan tanpa downtime, lakukan restart bergulir dua langkah:
Tambahkan
CooperativeStickyAssignorsebagai strategi sekunder bersama strategi saat ini, lalu lakukan restart bergulir pada semua consumer.props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG, "org.apache.kafka.clients.consumer.StickyAssignor," + "org.apache.kafka.clients.consumer.CooperativeStickyAssignor");Setelah semua consumer menerapkan konfigurasi baru, beralihlah hanya ke
CooperativeStickyAssignor, lalu lakukan restart bergulir lagi.props.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG, "org.apache.kafka.clients.consumer.CooperativeStickyAssignor");
Jangan gunakanStickyAssignorpada versi client sebelum 2.3. Bahkan setelah perbaikan,CooperativeStickyAssignorumumnya merupakan pilihan yang lebih baik karena mendukung rebalancing inkremental tanpa menghentikan semua consumer.