All Products
Search
Document Center

ApsaraMQ for Kafka:Mengapa sebuah partisi dikonsumsi oleh multiple consumer thread?

Last Updated:Mar 11, 2026

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:

  1. Consumer C1 bergabung ke kelompok consumer sebagai leader dan ditugaskan ke partisi test-0.

  2. Consumer C2 bergabung ke kelompok yang sama. C1 tetap mempertahankan test-0, sedangkan C2 tidak menerima partisi apa pun.

  3. C1 menjadi tidak responsif (misalnya, karena jeda GC yang lama). C2 kemudian menjadi leader baru dan mengambil alih test-0.

  4. C1 pulih dan kembali bergabung ke kelompok dengan penugasan lamanya (test-0). Baik C1 maupun C2 melaporkan test-0 sebagai penugasan yang sedang mereka miliki selama proses rebalancing.

  5. StickyAssignor tidak memeriksa duplikat, sehingga menugaskan test-0 ke 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:

StrategiNama kelasDeskripsiTrade-off
Range (default)RangeAssignorMendistribusikan 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-robinRoundRobinAssignorMenugaskan partisi satu per satu secara round-robin ke seluruh consumer.Lebih seimbang dibandingkan Range. Dapat menyebabkan lebih banyak perpindahan partisi selama rebalancing.
Cooperative stickyCooperativeStickyAssignorMenggunakan 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:

  1. Tambahkan CooperativeStickyAssignor sebagai 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");
  2. 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 gunakan StickyAssignor pada versi client sebelum 2.3. Bahkan setelah perbaikan, CooperativeStickyAssignor umumnya merupakan pilihan yang lebih baik karena mendukung rebalancing inkremental tanpa menghentikan semua consumer.