Kafka Producer Advanced: Producer Default Partitioner & Sticky Partitioner
Kafka Producer Default Partitioner & Sticky Partitioner
Dalam Apache Kafka, partitioner adalah proses yang menentukan ke partisi mana pesan tertentu akan dikirim oleh produser. Pemilihan partisi sangat penting untuk distribusi data yang seimbang, pengurutan pesan berdasarkan kunci, dan performa sistem secara keseluruhan. Kafka menyediakan Default Partitioner yang menangani pemetaan pesan berdasarkan kunci, serta strategi berbeda untuk kasus tanpa kunci: Round Robin Partitioner (Kafka ≤ 2.3) dan Sticky Partitioner (Kafka ≥ 2.4). Artikel ini akan menjelaskan cara kerja partitioner, perbedaan antara Round Robin dan Sticky Partitioner, serta langkah-langkah praktis untuk mengonfigurasi produser menggunakan kode Java dan alat CLI. Kami juga menyertakan praktik terbaik untuk mengoptimalkan performa dan latensi dalam lingkungan produksi.
Cara Kerja Partitioner di Kafka
Partitioner bertanggung jawab untuk memetakan pesan ke salah satu partisi dari topik berdasarkan kunci pesan (key) atau strategi lain jika kunci tidak ada. Pemilihan partisi memengaruhi distribusi data, pengurutan, dan efisiensi batching.
Partitioner Saat key != null
key != null
Jika pesan memiliki kunci (key), Default Partitioner Kafka menggunakan algoritma murmur2 untuk menghitung hash kunci dan memetakan pesan ke partisi tertentu. Rumusnya adalah:
targetPartition = Math.abs(Utils.murmur2(keyBytes)) % (numPartitions - 1)
Penjelasan:
keyBytes
: Representasi byte dari kunci pesan.Utils.murmur2
: Algoritma hashing murmur2 yang menghasilkan nilai hash.numPartitions
: Jumlah partisi dalam topik.Hasilnya adalah indeks partisi (0 hingga
numPartitions - 1
).
Implikasi:
Pesan dengan kunci yang sama selalu dikirim ke partisi yang sama, memastikan pengurutan (ordering) berdasarkan kunci.
Menambah partisi ke topik akan mengubah pemetaan kunci ke partisi, yang dapat mengganggu pengurutan jika aplikasi bergantung pada partisi tertentu.
Anda dapat mengganti Default Partitioner dengan menerapkan kelas kustom melalui
partitioner.class
, tetapi ini jarang diperlukan.
Partitioner Saat key == null
key == null
Jika pesan tidak memiliki kunci (key=null), Default Partitioner menggunakan strategi berikut berdasarkan versi Kafka:
Kafka ≤ 2.3: Round Robin Partitioner.
Kafka ≥ 2.4: Sticky Partitioner.
Round Robin Partitioner (Kafka ≤ 2.3)
Cara Kerja:
Saat
key=null
, Round Robin Partitioner mendistribusikan pesan secara bergilir ke semua partisi yang tersedia.Setiap batch pesan dikirim ke partisi berikutnya secara berurutan.
Kekurangan:
Batch Kecil: Dengan banyak partisi (misalnya, 100 partisi), setiap batch hanya berisi sedikit pesan, menghasilkan lebih banyak permintaan jaringan (network requests).
Latensi Tinggi: Batch kecil kurang efisien untuk kompresi dan meningkatkan overhead jaringan.
Throughput Rendah: Lebih banyak permintaan berarti throughput keseluruhan menurun.
Kasus Penggunaan:
Cocok untuk topik dengan jumlah partisi kecil atau ketika pengurutan tidak penting.
Sticky Partitioner (Kafka ≥ 2.4)
Cara Kerja:
Saat
key=null
, Sticky Partitioner memilih satu partisi secara acak dan "menempel" (stick) ke partisi tersebut hingga:Batch mencapai ukuran maksimum (
batch.size
), atauWaktu tunggu (
linger.ms
) habis.
Setelah batch dikirim, Sticky Partitioner memilih partisi baru secara acak untuk batch berikutnya.
Keuntungan:
Batch Besar: Mengisi batch untuk satu partisi sebelum beralih, menghasilkan batch yang lebih besar dan lebih efisien untuk kompresi.
Latensi Rendah: Mengurangi jumlah permintaan jaringan karena batch lebih besar.
Throughput Tinggi: Batch besar meningkatkan efisiensi pengiriman dan kompresi.
Distribusi Merata: Secara keseluruhan, pesan tetap terdistribusi merata di semua partisi, menjaga keseimbangan klaster.
Implikasi:
Sticky Partitioner adalah default pada Kafka ≥ 2.4 karena peningkatan performa yang signifikan, terutama untuk topik dengan banyak partisi.
Latensi lebih rendah terlihat jelas saat jumlah partisi meningkat.
Konfigurasi Produser dengan Sticky Partitioner
Untuk memanfaatkan Sticky Partitioner, gunakan konfigurasi produser berikut yang mengoptimalkan batching, kompresi, dan idempotence:
Properties properties = new Properties();
properties.setProperty(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
properties.setProperty(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
properties.setProperty(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
properties.setProperty(ProducerConfig.COMPRESSION_TYPE_CONFIG, "snappy");
properties.setProperty(ProducerConfig.LINGER_MS_CONFIG, "20");
properties.setProperty(ProducerConfig.BATCH_SIZE_CONFIG, Integer.toString(32 * 1024)); // 32KB
properties.setProperty(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, "true");
properties.setProperty(ProducerConfig.ACKS_CONFIG, "all");
properties.setProperty(ProducerConfig.RETRIES_CONFIG, Integer.toString(Integer.MAX_VALUE));
properties.setProperty(ProducerConfig.MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION, "5");
properties.setProperty(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, "120000");
Penjelasan:
Tidak perlu mengatur
partitioner.class
karena Sticky Partitioner adalah default pada Kafka ≥ 2.4 untukkey=null
.compression.type=snappy
: Mengoptimalkan efisiensi batch besar.linger.ms=20
danbatch.size=32768
: Meningkatkan ukuran batch untuk Sticky Partitioner.Idempotence dan
acks=all
memastikan pengiriman yang andal tanpa duplikasi.
Praktik Konfigurasi dan Pengujian
Berikut adalah langkah-langkah praktis untuk mengonfigurasi produser dengan Sticky Partitioner menggunakan kode Java dan alat CLI, serta pengujian untuk memverifikasi performa.
Prasyarat
Pastikan klaster Kafka berjalan (versi ≥ 2.4 untuk Sticky Partitioner, mode Zookeeper atau KRaft).
Gunakan ekstensi CLI yang sesuai:
.sh
untuk Linux/Mac,.bat
untuk Windows.Pastikan broker Kafka aktif di
localhost:9092
.Klaster memiliki setidaknya tiga broker untuk mendukung
replication.factor=3
.
Langkah-langkah Praktis
1. Buat Topik
Buat topik bernama sticky-topic
dengan 10 partisi, faktor replikasi 3, dan min.insync.replicas=2
:
kafka-topics.sh --bootstrap-server localhost:9092 --create --topic sticky-topic \
--partitions 10 --replication-factor 3 \
--config min.insync.replicas=2 \
--config compression.type=producer
Verifikasi konfigurasi topik:
kafka-topics.sh --bootstrap-server localhost:9092 --describe --topic sticky-topic
Contoh Keluaran:
Topic: sticky-topic TopicId: XYZ123 PartitionCount: 10 ReplicationFactor: 3 Configs: min.insync.replicas=2,compression.type=producer
Topic: sticky-topic Partition: 0 Leader: 1 Replicas: 1,2,3 Isr: 1,2,3
...
Topic: sticky-topic Partition: 9 Leader: 2 Replicas: 2,3,1 Isr: 2,3,1
2. Implementasi Produser dengan Sticky Partitioner (Java)
Berikut adalah contoh kode Java untuk produser yang menggunakan Sticky Partitioner (dengan key=null
):
import org.apache.kafka.clients.producer.*;
import org.apache.kafka.common.serialization.StringSerializer;
import java.util.Properties;
public class StickyProducer {
public static void main(String[] args) {
// Konfigurasi produser
Properties properties = new Properties();
properties.setProperty(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
properties.setProperty(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
properties.setProperty(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
properties.setProperty(ProducerConfig.COMPRESSION_TYPE_CONFIG, "snappy");
properties.setProperty(ProducerConfig.LINGER_MS_CONFIG, "20");
properties.setProperty(ProducerConfig.BATCH_SIZE_CONFIG, Integer.toString(32 * 1024)); // 32KB
properties.setProperty(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, "true");
properties.setProperty(ProducerConfig.ACKS_CONFIG, "all");
properties.setProperty(ProducerConfig.RETRIES_CONFIG, Integer.toString(Integer.MAX_VALUE));
properties.setProperty(ProducerConfig.MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION, "5");
properties.setProperty(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, "120000");
// Buat produser
KafkaProducer<String, String> producer = new KafkaProducer<>(properties);
// Kirim pesan tanpa kunci (menggunakan Sticky Partitioner)
for (int i = 0; i < 1000; i++) {
String value = "{\"id\": " + i + ", \"data\": \"High throughput message without key\"}";
ProducerRecord<String, String> record = new ProducerRecord<>("sticky-topic", null, value);
producer.send(record, (metadata, exception) -> {
if (exception == null) {
System.out.printf("Pesan dikirim: value=%s, partition=%d, offset=%d%n",
value, metadata.partition(), metadata.offset());
} else {
System.err.printf("Gagal mengirim pesan: %s%n", exception.getMessage());
}
});
}
// Tutup produser
producer.flush();
producer.close();
}
}
Penjelasan Kode:
Menggunakan
key=null
untuk memicu Sticky Partitioner (default pada Kafka ≥ 2.4).Mengoptimalkan batching dengan
linger.ms=20
danbatch.size=32768
.Mengaktifkan kompresi
snappy
untuk efisiensi batch besar.Mengirim 1000 pesan JSON untuk menguji throughput dengan Sticky Partitioner.
3. Uji dengan Produser Konsol
Jalankan produser konsol dengan Sticky Partitioner (dengan key=null
):
kafka-console-producer.sh --bootstrap-server localhost:9092 \
--topic sticky-topic \
--producer-property compression.type=snappy \
--producer-property linger.ms=20 \
--producer-property batch.size=32768 \
--producer-property enable.idempotence=true \
--producer-property acks=all \
--producer-property retries=2147483647 \
--producer-property max.in.flight.requests.per.connection=5 \
--producer-property delivery.timeout.ms=120000
Kirim beberapa pesan tanpa kunci:
{"id": 1, "data": "Sticky partition message"}
{"id": 2, "data": "Another sticky message"}
{"id": 3, "data": "Optimized sticky data"}
4. Konsumsi Pesan
Jalankan konsumer untuk memverifikasi pesan dan distribusi partisi:
kafka-console-consumer.sh --bootstrap-server localhost:9092 \
--topic sticky-topic \
--from-beginning \
--property print.partition=true
Contoh Keluaran:
Partition: 3 {"id": 1, "data": "Sticky partition message"}
Partition: 3 {"id": 2, "data": "Another sticky message"}
Partition: 3 {"id": 3, "data": "Optimized sticky data"}
Partition: 7 {"id": 4, "data": "Next batch message"}
...
Catatan: Pesan awal akan terkonsentrasi pada satu partisi (sticky), kemudian beralih ke partisi lain setelah batch penuh atau linger.ms
habis.
5. Uji Performa Sticky Partitioner
Pantau Throughput: Gunakan metrik JMX seperti
BytesOutPerSec
untuk membandingkan Sticky Partitioner dengan Round Robin Partitioner (simulasikan Round Robin pada Kafka < 2.4 jika memungkinkan).Periksa Latensi: Gunakan metrik
RequestLatencyAvg
untuk memastikan latensi lebih rendah dengan Sticky Partitioner.Verifikasi Distribusi Partisi:
kafka-run-class.sh kafka.tools.GetOffsetShell --broker-list localhost:9092 --topic sticky-topic
Periksa jumlah pesan per partisi untuk memastikan distribusi merata dalam jangka panjang.
Uji dengan Partisi Banyak: Ulangi pengujian dengan topik yang memiliki 50 atau 100 partisi untuk melihat manfaat Sticky Partitioner pada skala besar.
Catatan
Pengaruh Penambahan Partisi: Menambah partisi mengubah pemetaan kunci pada Default Partitioner (saat
key != null
). Untuk Sticky Partitioner, ini tidak memengaruhi pengurutan, tetapi distribusi batch akan menyesuaikan dengan jumlah partisi baru.Mode KRaft: Sticky Partitioner bekerja sama di mode KRaft, dengan manajemen partisi yang lebih efisien karena controller Kafka.
Kustom Partitioner: Jika diperlukan, Anda dapat mengimplementasikan kelas kustom dengan
partitioner.class
, tetapi Sticky Partitioner biasanya cukup untuk sebagian besar kasus.
Praktik Terbaik
Gunakan Sticky Partitioner untuk Throughput Tinggi:
Manfaatkan Sticky Partitioner (default pada Kafka ≥ 2.4) untuk
key=null
guna meningkatkan ukuran batch dan mengurangi latensi.
Optimalkan Batching:
Gunakan
linger.ms=20
danbatch.size=32768
untuk memaksimalkan ukuran batch dengan Sticky Partitioner.Kombinasikan dengan
compression.type=snappy
untuk efisiensi lebih tinggi.
Gunakan Kunci untuk Pengurutan:
Jika pengurutan berdasarkan kunci diperlukan, selalu tentukan
key
untuk memanfaatkan hashing murmur2.Hindari menambah partisi pada topik yang sudah ada jika aplikasi bergantung pada pengurutan kunci.
Pantau Performa:
Gunakan metrik JMX seperti
BytesOutPerSec
,RequestLatencyAvg
, danBatchSizeAvg
untuk memantau efisiensi Sticky Partitioner.Periksa distribusi pesan antar partisi untuk memastikan keseimbangan klaster:
kafka-run-class.sh kafka.tools.GetOffsetShell --broker-list localhost:9092 --topic sticky-topic
Uji di Lingkungan Non-Produksi:
Uji Sticky Partitioner dengan topik yang memiliki banyak partisi (misalnya, 50 atau 100) untuk memverifikasi peningkatan performa dibandingkan Round Robin.
Kombinasikan dengan Idempotence:
Aktifkan
enable.idempotence=true
untuk mencegah duplikasi, terutama saat menggunakan Sticky Partitioner dengan retries.
Hindari Partitioner Kustom Kecuali Diperlukan:
Default Partitioner (dengan Sticky Partitioner untuk
key=null
) cukup untuk sebagian besar kasus penggunaan.
Dokumentasikan Konfigurasi:
Catat apakah Anda mengandalkan Sticky Partitioner atau kunci untuk pemetaan partisi, serta alasan pemilihannya.
Penjelasan Tambahan
Hubungan dengan Batching dan Kompresi
Sticky Partitioner meningkatkan efisiensi batching karena mengisi batch untuk satu partisi sebelum beralih, menghasilkan batch besar yang lebih cocok untuk kompresi.
Parameter seperti
linger.ms
,batch.size
, dancompression.type
bekerja sinergis dengan Sticky Partitioner untuk mengoptimalkan throughput dan latensi.
Pemecahan Masalah
Jika throughput rendah:
Periksa
linger.ms
danbatch.size
:Tingkatkan
linger.ms
ke20
ataubatch.size
ke65536
untuk batch lebih besar.
Periksa Kompresi:
Pastikan
compression.type=snappy
ataulz4
diaktifkan untuk data berbasis teks.
Verifikasi Versi Kafka:
Pastikan Anda menggunakan Kafka ≥ 2.4 untuk Sticky Partitioner. Jika menggunakan versi lama, pertimbangkan upgrade.
Jika distribusi partisi tidak merata:
Periksa jumlah pesan per partisi:
kafka-run-class.sh kafka.tools.GetOffsetShell --broker-list localhost:9092 --topic sticky-topic
Sticky Partitioner mendistribusikan pesan merata dalam jangka panjang, tetapi distribusi sementara mungkin tampak tidak merata karena "menempel" pada satu partisi.
Jika pengurutan kunci terganggu:
Pastikan kunci ditentukan (
key != null
) untuk pesan yang memerlukan pengurutan.Hindari menambah partisi pada topik yang sudah ada.
Kesimpulan
Partitioner pada produser Kafka menentukan bagaimana pesan dipetakan ke partisi, memengaruhi pengurutan, distribusi, dan performa. Default Partitioner menggunakan hashing murmur2 untuk kunci, memastikan pesan dengan kunci yang sama masuk ke partisi yang sama. Untuk pesan tanpa kunci, Sticky Partitioner (default pada Kafka ≥ 2.4) meningkatkan performa dengan mengisi batch besar untuk satu partisi sebelum beralih, mengurangi latensi dan meningkatkan throughput dibandingkan Round Robin Partitioner (Kafka ≤ 2.3). Contoh kode Java dan CLI menunjukkan cara menerapkan Sticky Partitioner dengan konfigurasi optimal, sementara praktik terbaik seperti pengujian, pemantauan metrik, dan dokumentasi memastikan operasi yang efisien. Sticky Partitioner sangat direkomendasikan untuk aplikasi dengan throughput tinggi, terutama pada topik dengan banyak partisi.
Last updated