Jumlah partisi

Menetapkan jumlah partisi dari throughput dan paralelisme consumer beserta biaya mengubahnya di kemudian hari.

Daftar isi

Jumlah partisi adalah keputusan desain pertama yang diambil saat sebuah topic dibuat karena nilai itu menetapkan kapasitas tulis topic sekaligus tingkat paralelisme pembacaannya. Topik ini menjelaskan pertimbangan yang memengaruhi jumlah partisi, perhitungan yang menghasilkan angka awal, perintah untuk menambah partisi pada topic yang sudah ada, dan risiko penambahan partisi pada topic yang menggunakan key. Setelah membaca topik ini, jumlah partisi dapat ditetapkan berdasarkan angka yang dapat dihitung ulang.

Pertimbangan jumlah partisi#

Partisi adalah unit paralelisme pada Kafka. Producer menulis ke beberapa partisi secara serentak, sedangkan consumer group membagikan partisi kepada anggotanya sehingga setiap consumer mengerjakan partisi yang berbeda. Kapasitas tulis seluruh topic, yang lazim disebut throughput, mendekati penjumlahan kapasitas semua partisinya, dan jumlah consumer yang benar-benar bekerja tidak dapat melebihi jumlah partisi. Dua batas itulah yang menjadi dasar penentuan jumlah partisi.

Tabel berikut merangkum sisi-sisi yang terpengaruh ketika jumlah partisi ditambah.

SisiPertimbanganDampak menambah partisi
ProducerThroughput penulisan totalKapasitas tulis bertambah karena beban terbagi ke lebih banyak partisi
Consumer groupJumlah consumer yang bekerja serentakBatas paralelisme pembacaan naik
BrokerBerkas log terbuka dan lalu lintas replikasiBeban broker bertambah untuk setiap partisi baru
AplikasiJaminan pengurutan per keyPengurutan dalam satu partisi tetap, tetapi pemetaan key ke partisi berubah

Setiap partisi membutuhkan satu berkas log di broker, satu alur replikasi, dan satu slot pada pembagian tugas consumer group. Topic dengan jumlah partisi yang besar memerlukan sumber daya broker yang tidak sedikit, sehingga penambahan partisi dilakukan dengan alasan throughput atau paralelisme yang jelas. Penambahan juga bersifat satu arah karena Kafka tidak menyediakan pengurangan jumlah partisi. Nilai yang ditetapkan pada awal pembuatan topic dengan demikian perlu diperhitungkan dengan cermat.

Perhitungan jumlah partisi#

Jumlah partisi minimal dihitung dari throughput yang harus dicapai oleh topic. Apabila throughput total yang dituju dinyatakan TtotalT_{\text{total}} dan perkiraan throughput yang mampu ditulis ke satu partisi dinyatakan TpartisiT_{\text{partisi}}, jumlah partisi minimal dari sisi penulisan mengikuti

n≥⌈TtotalTpartisi⌉ n \geq \left\lceil \frac{T_{\text{total}}}{T_{\text{partisi}}} \right\rceil

Perhitungan yang sama diulang dari sisi pembacaan dengan membagi throughput total dengan throughput yang mampu dibaca oleh satu consumer. Nilai terbesar dari kedua hasil dipilih karena hambatan dapat berada di salah satu sisi saja. Skrip berikut menghitung contoh konkret, yaitu topic yang harus menampung 60 MB per detik dengan perkiraan 10 MB per detik untuk penulisan satu partisi dan 15 MB per detik untuk pembacaan satu consumer.

python hitung-partisi.py
import math

# angka contoh dalam megabyte per detik
target_total = 60      # throughput yang harus dicapai seluruh topic
per_partisi = 10       # perkiraan throughput producer per partisi
per_consumer = 15      # perkiraan throughput satu consumer

n_producer = math.ceil(target_total / per_partisi)
n_consumer = math.ceil(target_total / per_consumer)
n_pilih = max(n_producer, n_consumer)

print(f"partisi dari sisi producer : {n_producer}")
print(f"partisi dari sisi consumer : {n_consumer}")
print(f"jumlah partisi terpilih    : {n_pilih}")
text Keluaran
partisi dari sisi producer : 6
partisi dari sisi consumer : 4
jumlah partisi terpilih    : 6

Nilai dari sisi producer adalah 6 karena 60 dibagi 10, sedangkan nilai dari sisi consumer adalah 4 karena 60 dibagi 15. Jumlah partisi terpilih adalah 6, yaitu nilai yang lebih besar, karena memilih 4 membuat sisi penulisan menjadi hambatan. Angka dalam skrip merupakan perkiraan awal dan bukan hasil pengukuran, sehingga setelah topic berjalan nilai tersebut diuji ulang dengan data aktual. Ruang tumbuh disediakan dengan menghitung berdasarkan target yang lebih besar dari beban hari ini, misalnya dua kali lipat, karena jumlah partisi tidak dapat dikurangi kembali.

Menambah partisi pada topic yang sudah ada#

Perintah pembuatan topic menerima opsi --partitions, dan jumlah itu tetap berlaku sampai diubah secara eksplisit. Perintah berikut membuat topic demo baru dengan tiga partisi, lalu menampilkan deskripsinya. Baris kepala deskripsi disaring menggunakan grep sehingga keluarannya hanya memuat baris per partisi.

bash
(
  cd /home/kal/my-project/kafka-runtime/kafka
  bin/kafka-topics.sh --bootstrap-server localhost:9092 --delete --if-exists --topic m2-partisi-demo 2>/dev/null
  sleep 2
  bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --topic m2-partisi-demo --partitions 3
  bin/kafka-topics.sh --bootstrap-server localhost:9092 --describe --topic m2-partisi-demo | grep "Partition:" | expand
)
text Keluaran
Created topic m2-partisi-demo.
        Topic: m2-partisi-demo  Partition: 0    Leader: 1       Replicas: 1     Isr: 1  Elr:    LastKnownElr: 
        Topic: m2-partisi-demo  Partition: 1    Leader: 1       Replicas: 1     Isr: 1  Elr:    LastKnownElr: 
        Topic: m2-partisi-demo  Partition: 2    Leader: 1       Replicas: 1     Isr: 1  Elr:    LastKnownElr: 

Keluaran memuat satu baris untuk setiap partisi, mulai dari Partition: 0 sampai Partition: 2, sehingga jumlah partisi terlihat langsung dari hasil perintah. Setiap baris menyebut Leader: 1 dan Isr: 1 karena demo ini berjalan pada broker tunggal, dan setiap partisi hanya memiliki satu replika. Pada topic yang sudah ada, penambahan jumlah partisi dilakukan dengan opsi --alter, misalnya bin/kafka-topics.sh --bootstrap-server localhost:9092 --alter --topic m2-partisi-demo --partitions 6. Partisi yang baru ditambahkan hanya menerima pesan yang ditulis setelahnya, sedangkan pesan lama beserta offset-nya tetap berada di partisi semula.

Risiko penambahan partisi pada topic berkunci#

Producer memetakan key ke partisi melalui fungsi hash, kemudian menerapkan operasi modulo terhadap jumlah partisi. Pemetaan ini stabil hanya selama jumlah partisi tidak berubah. Ketika jumlah partisi naik dari tiga menjadi enam, hampir semua key berpindah partisi karena hasil modulo ikut berubah.

Pergeseran pemetaan itu membawa dua akibat yang perlu diantisipasi. Pesan dengan key yang sama dapat tercatat pada partisi berbeda setelah penambahan, sehingga jaminan pengurutan per key tidak lagi mencakup pesan lama dan pesan baru sekaligus. Selain itu, consumer yang menyimpan keadaan per key pada memori atau penyimpanan turunan yang dibangun dari aliran pesan menerima campuran data dari pemetaan lama dan pemetaan baru. Pada topic tanpa key, pergeseran semacam ini tidak muncul karena distribusi pesan tidak bergantung pada key.

Karena itu, jumlah partisi topic berkunci sebaiknya ditetapkan sejak awal dengan ruang tumbuh yang cukup. Bila kebutuhan paralelisme benar-benar melonjak, pilihan yang lebih aman adalah membuat topic baru dengan jumlah partisi lebih besar dan memindahkan aliran ke sana dalam satu kali perpindahan. Cara tersebut menjaga pemetaan key tetap stabil selama masa pakai topic.

Ringkasan#

  • Jumlah partisi menetapkan kapasitas tulis topic dan jumlah consumer yang bekerja serentak dalam satu consumer group.
  • Jumlah partisi awal dihitung dari throughput total dibagi throughput per partisi dan dibagi throughput per consumer, lalu diambil nilai terbesar dari keduanya.
  • Penambahan partisi dilakukan dengan --alter --partitions, tidak dapat dibatalkan, dan partisi baru hanya menerima pesan baru.
  • Pada topic berkunci, penambahan partisi mengubah pemetaan key sehingga urutan per key antara pesan lama dan pesan baru tidak dijaga.

Referensi#