Zookeeper vs KRaft #

Dalam evolusi teknologi infrastruktur data terdistribusi, cara sebuah kluster berkoordinasi untuk mengelola status metadatanya adalah salah satu keputusan arsitektural terpenting yang menentukan batas skalabilitas sistem. Selama lebih dari satu dekade, Apache Kafka sangat bergantung pada Apache ZooKeeper sebagai sistem koordinasi eksternal untuk mengelola status broker, topik, partisi, dan penunjukan pemimpin. Namun, arsitektur sistem ganda ini melahirkan berbagai masalah kompleksitas operasional, kerentanan sinkronisasi, dan keterbatasan jumlah partisi fisik.

Sebagai solusinya, Kafka era modern memperkenalkan KRaft (Kafka Raft Metadata Mode) yang menyatukan manajemen metadata langsung ke dalam broker Kafka menggunakan protokol konsensus Raft yang dioptimalkan secara mendalam. Di artikel ini, kita akan membedah secara mendalam perbedaan arsitektur ZooKeeper vs KRaft, mengapa KRaft mampu melipatgandakan batas kapasitas partisi hingga jutaan partisi, alur failover pengontrol metadata, serta panduan praktis konfigurasi parameter quorum dan inisialisasi kluster KRaft di server kita.

Era Klasik: Koordinasi dengan Apache ZooKeeper #

Pada arsitektur Kafka klasik (versi 2.x ke bawah), kluster Kafka tidak dapat berjalan sendiri. Kita wajib menjalankan kluster Apache ZooKeeper (biasanya disebut ZooKeeper Ensemble dengan minimal 3 node) di samping broker-broker Kafka kita.

Di dalam topologi ini, pembagian tanggung jawab data dan metadata dipisahkan secara kaku:

  • Penyimpanan Data: Broker Kafka hanya bertanggung jawab atas penyimpanan log biner fisik dan melayani request klien.
  • Penyimpanan Metadata: ZooKeeper bertindak sebagai single source of truth untuk seluruh status kluster. ZooKeeper menyimpan struktur pohon hierarkis biner (znodes) yang berisi data tentang: broker aktif, konfigurasi topik, batas kuota klien, serta daftar In-Sync Replicas (ISR) dan Leader untuk setiap partisi.

Peran Controller Broker dan Mekanisme Watcher #

Untuk berinteraksi dengan ZooKeeper, kluster Kafka menunjuk salah satu broker beralih tugas menjadi Controller melalui mekanisme perebutan kunci (znode locking) di ZooKeeper. Controller bertindak sebagai jembatan tunggal:

  1. Controller memasang pengamat (Watcher) pada znodes ZooKeeper.
  2. Ketika terjadi peristiwa perubahan status (misalnya, ada broker data yang mati), ZooKeeper akan memicu Watch Notification ke Controller.
  3. Controller membaca status terbaru dari ZooKeeper, memperbarui memori lokalnya, lalu mengirimkan perintah pembaruan metadata biner (LeaderAndIsrRequest dan UpdateMetadataRequest) ke seluruh broker data yang tersisa di kluster melalui koneksi TCP.

Kelemahan Fatal ZooKeeper #

Meskipun ZooKeeper bekerja dengan sangat baik untuk kluster berskala kecil, arsitektur ini memiliki kelemahan fatal ketika volume data dan jumlah partisi di dalam kluster kita membengkak:

  1. Bottleneck Sinkronisasi Serial (Metadata Bottleneck) Ketika sebuah broker yang memimpin puluhan ribu partisi mati mendadak, Controller harus melakukan pemilihan pemimpin baru untuk puluhan ribu partisi tersebut. Controller harus menulis perubahan ini ke ZooKeeper satu per satu secara berurutan (serial write). ZooKeeper kemudian memproses dan mengembalikan respon sukses, barulah Controller menyebarkan informasi metadata baru ini ke seluruh broker di kluster. Proses sinkronisasi berantai ini sangat lambat. Pada kluster besar dengan lebih dari 50.000 partisi, waktu pemulihan (recovery time) setelah kegagalan broker bisa memakan waktu 20 hingga 40 menit, di mana selama waktu tersebut kluster tidak stabil.
  2. Keterbatasan Jumlah Watch Jaringan Setiap kali ada perubahan status partisi, ZooKeeper harus memicu notifikasi ke Controller. Ketika jumlah partisi mencapai ratusan ribu, jumlah watcher aktif pada ZooKeeper membengkak secara eksponensial. Ini memakan bandwidth jaringan dan RAM yang sangat besar di sisi ZooKeeper. Jika ZooKeeper mengalami kemacetan jaringan, ia dapat memutus koneksi sesi dengan Controller secara sepihak, memicu pemilihan Controller baru secara liar (cascade controller election) yang memperparah kekacauan kluster.
  3. GC Pause dan Kerentanan Split-Brain Jika proses JVM pada broker Controller mengalami pembekuan memori (Garbage Collection pause) yang lama, Controller akan berhenti merespon ZooKeeper. ZooKeeper menganggap Controller tersebut mati karena session timeout terlampaui, dan segera memilih broker lain menjadi Controller baru. Ketika Controller lama terbangun dari GC pause, ia mungkin tidak menyadari bahwa ia telah diturunkan tahtanya. Hal ini dapat memicu fenomena Split-Brain (terdapat dua broker yang sama-sama merasa menjadi Controller aktif), yang sering kali berujung pada kerusakan metadata kluster.
  4. Overhead Operasional Ganda Bagi tim operasional infrastruktur kita, memelihara dua sistem terdistribusi yang berbeda adalah beban berat. ZooKeeper memiliki format konfigurasi, port jaringan, mekanisme keamanan (SASL/JAAS), dan sistem monitoring yang sepenuhnya berbeda dengan Kafka. Keamanan SSL harus dikonfigurasi dua kali: satu untuk Kafka-ke-Kafka, dan satu lagi untuk Kafka-ke-ZooKeeper.

Era Modern: Konsensus Terintegrasi dengan KRaft #

Mulai versi 3.0 dan menjadi standar wajib di versi 4.0, Apache Kafka membuang ZooKeeper sepenuhnya dan beralih menggunakan KRaft (Kafka Raft). Dalam mode KRaft, Kafka mengadopsi protokol konsensus Raft yang dimodifikasi khusus untuk kebutuhan event streaming metadata.

Di bawah arsitektur KRaft, kluster Kafka tidak lagi bergantung pada sistem eksternal. Manajemen metadata dijalankan secara internal oleh broker Kafka yang ditunjuk sebagai Controller Quorum:

  • Controller Quorum: Sekelompok broker khusus (biasanya 3 atau 5 node untuk kluster produksi) menjalankan peran sebagai Controller.
  • Active Controller: Salah satu anggota Quorum dipilih melalui konsensus Raft sebagai pemimpin aktif (Leader), sementara anggota Quorum lainnya bertindak sebagai cadangan hangat (standby/Followers).
  • Metadata Log: Semua metadata kluster disimpan di dalam topik internal rahasia bernama @metadata yang direplikasi di antara seluruh anggota Controller Quorum menggunakan mesin konsensus Raft. Setiap broker data biasa (Data Broker) juga terus melakukan sinkronisasi asinkron terhadap log metadata ini.

Konsep Metadata Image dan Metadata Delta #

Salah satu rahasia kecepatan KRaft adalah penggunaan struktur data Metadata Image dan Metadata Delta di dalam memori RAM setiap broker:

  • Metadata Image: Representasi status kluster yang sepenuhnya jadi (fully materialized view) di dalam memori broker. Broker dapat membaca status kluster secara instan dengan kompleksitas O(1) dari RAM tanpa perlu kueri jaringan.
  • Metadata Delta: Perubahan parsial (diff) yang dihasilkan oleh Active Controller ketika ada kejadian baru (misalnya, pembuatan topik). Delta ini ditulis ke topik @metadata dan disiarkan ke seluruh broker. Broker kemudian menerapkan delta ini ke Metadata Image lokal mereka untuk memperbarui status secara asinkron dan sangat cepat.

Keunggulan Utama Arsitektur KRaft #

KRaft memecahkan seluruh kelemahan arsitektur ZooKeeper secara elegan:

  1. Pemulihan Kegagalan Sekejap Mata (Sub-Second Failover) Karena seluruh anggota Controller Quorum cadangan (standby) terus melakukan replikasi log metadata secara real-time menggunakan Raft, mereka memelihara salinan status metadata yang persis sama di dalam memori mereka (Warm Standby). Ketika Active Controller mati mendadak, quorum akan memilih Active Controller baru dalam hitungan milidetik. Controller baru ini tidak perlu melakukan inisialisasi ulang atau membaca data dari database eksternal; ia bisa langsung memproses request metadata kluster secara instan karena datanya sudah ada di memori lokalnya.
  2. Skalabilitas Luar Biasa (Hingga Jutaan Partisi) Karena metadata dikelola dalam bentuk commit log internal Kafka yang sangat dioptimalkan, KRaft mampu menangani hingga jutaan partisi per kluster tanpa degradasi performa. Batas partisi per broker tidak lagi dibatasi oleh kinerja sistem koordinasi eksternal.
  3. Penyederhanaan Infrastruktur Kita cukup mengelola satu jenis teknologi perangkat lunak (Kafka). Hanya ada satu jenis file konfigurasi, satu protokol keamanan jaringan, satu metode sertifikat SSL, dan satu sistem monitoring metrik. Ini mengurangi kompleksitas deployment dan biaya operasional tim infrastruktur kita secara signifikan.

Perbandingan Arsitektur: ZooKeeper vs KRaft #

Mari kita bandingkan perbedaan topologi koordinasi cluster era ZooKeeper dengan arsitektur modern terpadu berbasis KRaft melalui diagram komparatif berikut:

flowchart TD
    subgraph EraZK ["Era Klasik: Koordinasi ZooKeeper"]
        direction TB
        ZK["ZooKeeper Ensemble <br/> (External Cluster)"] <===>|"Watch & Metadata Sync"| CtrlBroker["Kafka Broker (Controller)"]
        CtrlBroker -->|"LeaderAndIsr / UpdateMetadata"| DB1["Data Broker 1"]
        CtrlBroker -->|"LeaderAndIsr / UpdateMetadata"| DB2["Data Broker 2"]
    end

    subgraph EraKRaft ["Era Modern: Konsensus KRaft"]
        direction TB
        subgraph Quorum ["Controller Quorum (Raft)"]
            ActiveCtrl["Active Controller <br/> (Raft Leader)"] <== Replikasi Raft ==> StandbyCtrl["Standby Controller <br/> (Raft Follower)"]
        end
        ActiveCtrl -. Metadata Publish .-> KDB1["Data Broker 1"]
        ActiveCtrl -. Metadata Publish .-> KDB2["Data Broker 2"]
    end

    style ZK fill:#ffdddd,stroke:#ff8888
    style Quorum fill:#ddffdd,stroke:#88ff88
    style ActiveCtrl fill:#ddffdd,stroke:#88ff88

Panduan Inisialisasi dan Penyetelan Parameter KRaft #

Untuk mengaktifkan mode KRaft, kita harus mendefinisikan properti konfigurasi khusus di dalam file konfigurasi broker kita (misalnya config/kraft/server.properties). Berikut adalah parameter kunci yang wajib kita setel:

Parameter Konfigurasi Kunci #

  • process.roles: Menentukan peran dari node tersebut. Nilai yang valid adalah:
    • broker — Bertindak sebagai data broker biasa yang mengelola topik data bisnis.
    • controller — Bertindak sebagai pengelola metadata (anggota Controller Quorum).
    • broker,controller — Node memainkan peran ganda (shared/combi mode). Hanya cocok untuk lingkungan pengembangan (development) atau kluster kecil non-kritis.
  • node.id: Nomor identitas integer unik untuk node tersebut (menggantikan peran broker.id pada era ZooKeeper).
  • controller.quorum.voters: Daftar seluruh anggota Controller Quorum beserta alamat dan port kominukasinya. Formatnya adalah node_id1@host1:port1,node_id2@host2:port2,....
  • listeners: Port protokol jaringan yang didengarkan oleh server. Untuk koneksi controller, kita harus menyertakan nama port internal khusus metadata (biasanya menggunakan port 9093 dengan nama listener CONTROLLER).
    • Contoh: listeners=PLAINTEXT://:9092,CONTROLLER://:9093
  • metadata.log.dir: Direktori penyimpanan log metadata KRaft (topik @metadata). Sangat disarankan untuk memisahkan direktori ini ke disk fisik yang berbeda dengan data topik bisnis kita untuk menghindari intervensi I/O.

Langkah Inisialisasi Kluster KRaft via Command Line #

Setelah file konfigurasi disiapkan, kita harus melakukan format metadata storage sebelum dapat menjalankan kluster. Berikut adalah langkah-langkah eksekusi perintahnya:

Langkah 1: Generate Cluster ID Unik #

Kita harus membuat UUID unik yang akan bertindak sebagai pengenal resmi kluster kita. Jalankan perintah:

# Membuat ID kluster unik menggunakan skrip bawaan Kafka
bin/kafka-storage.sh random-bootstrap-id

Output dari perintah ini berupa string UUID unik, misalnya: J8n-o5w2R3S7pE8fX9gQ1w

Langkah 2: Format Penyimpanan Metadata #

Jalankan perintah format pada setiap broker dengan menyertakan UUID yang kita dapatkan pada langkah 1:

# Format direktori penyimpanan log dengan cluster ID
bin/kafka-storage.sh format \
  -t J8n-o5w2R3S7pE8fX9gQ1w \
  -c config/kraft/server.properties

Langkah 3: Jalankan Broker Kafka #

Setelah berhasil diformat, kita dapat langsung menjalankan server broker menggunakan properti KRaft:

# Menjalankan server Kafka dalam mode KRaft
bin/kafka-server-start.sh config/kraft/server.properties

Alat Debugging: kafka-metadata-shell #

Salah satu tantangan di era KRaft adalah hilangnya ZooKeeper CLI (zookeeper-shell.sh) yang biasa digunakan developer untuk menginspeksi metadata secara langsung. Sebagai gantinya, Kafka menyediakan alat baru bernama kafka-metadata-shell.sh.

Alat ini memungkinkan kita untuk membaca berkas log metadata @metadata secara interaktif seperti menjelajahi direktori lokal menggunakan perintah linux standar (ls, cd, cat).

# Menjalankan metadata shell untuk membaca log biner KRaft
bin/kafka-metadata-shell.sh --snapshot /tmp/kafka-metadata-logs/__cluster_metadata-0/00000000000000000000.log

# Di dalam shell, kita bisa melakukan navigasi:
>> ls /
brokers  features  local  metadataQuorum  topicIds  topics
>> cd /brokers
>> ls
1  2  3
>> cat 1/registration
{"brokerId":1,"incarnationId":"...","listeners":{"PLAINTEXT":{"host":"localhost","port":9092}},...}

Alat ini sangat berguna bagi kita untuk mendiagnosis status registrasi broker, struktur partisi topik, dan konfigurasi kluster secara langsung dari file biner log metadata.


Anti-pattern vs Solusi: Konfigurasi Quorum Produksi #

Banyak pengembang melakukan kesalahan fatal saat merancang topologi Controller Quorum di lingkungan produksi karena salah memahami sifat konsensus Raft.

1. Menggunakan 2 Controller Node #

Beberapa tim memilih menyebarkan 2 Controller Node dengan tujuan menghemat sumber daya server, menganggap memiliki 1 cadangan sudah cukup.

Konsekuensi Kegagalan: Raft menggunakan formula kuorum mayoritas mutlak:

$$\text{Minimum Quorum} = \lfloor \frac{N}{2} \rfloor + 1$$

Di mana $N$ adalah jumlah total anggota pemilih (voters).

  • Jika $N = 2$, maka jumlah kuorum mayoritas yang dibutuhkan adalah $\lfloor 2/2 \rfloor + 1 = 2$.
  • Jika salah satu dari 2 Controller tersebut mengalami kegagalan, jumlah Controller yang hidup tinggal 1. Karena 1 lebih kecil daripada batas minimum kuorum (2), maka Controller Quorum akan mogok total secara instan. Kita tidak memiliki toleransi kegagalan sama sekali.
  • Selalu gunakan jumlah ganjil minimal 3 controller (toleransi kerusakan 1 node) atau 5 controller (toleransi kerusakan 2 node) di lingkungan produksi kita.

2. Mencampurkan Peran Broker dan Controller di Produksi Berat #

Menyetel konfigurasi process.roles = broker,controller untuk seluruh node di kluster produksi berskala besar guna menyederhanakan manajemen server.

Konsekuensi Kegagalan: Saat broker data mengalami lalu lintas data yang sangat padat, thread JVM heap akan mengalami Garbage Collection yang intensif dan beban CPU I/O disk akan sangat tinggi. Jika node tersebut juga bertugas mengelola konsensus metadata KRaft, GC pause yang lama dapat memicu pengeluaran node tersebut dari quorum konsensus. Kluster akan mengalami ketidakstabilan koordinasi metadata akibat terganggunya proses internal data.

Selalu pisahkan peran secara tegas di lingkungan produksi: jalankan 3 server kecil khusus sebagai dedicated controller (process.roles = controller) dan server lainnya sebagai dedicated broker (process.roles = broker).


Ringkasan #

  • ZooKeeper Mode — Topologi klasik Kafka di mana status metadata kluster dikelola di cluster ZooKeeper eksternal dan disebarkan oleh satu broker Controller terpilih.
  • KRaft Mode — Arsitektur modern Kafka yang mengintegrasikan koordinasi metadata langsung ke dalam broker menggunakan protokol konsensus Raft yang dioptimalkan.
  • Raft Metadata Log — Topik internal @metadata di KRaft yang mereplikasi seluruh transaksi konfigurasi kluster ke seluruh pengontrol secara aman dan konsisten.
  • Controller Quorum — Kelompok broker khusus yang ditunjuk untuk mengelola metadata, terdiri dari satu Active Controller (Leader) dan beberapa Standby Controller (Followers).
  • Pemulihan Cepat — KRaft memotong waktu pemulihan kluster (failover) dari hitungan puluhan menit di era ZooKeeper menjadi hanya beberapa milidetik saja karena metadata dipelihara langsung di memori standby.
  • Format Storage — Penggunaan utilitas kafka-storage.sh wajib dilakukan untuk mengikat kluster di bawah satu Cluster ID UUID yang sama sebelum broker dijalankan.
  • Quorum Ganjil — Sesuai aturan konsensus mayoritas Raft, jumlah controller wajib berjumlah ganjil (minimal 3) untuk menghindari kebuntuan pemilihan pemimpin (quorum deadlock).
  • Pemisahan Peran — Jalankan dedicated controller yang terpisah dari broker data pada kluster produksi guna menghindari gangguan konsensus akibat beban I/O data atau GC pause.

← Sebelumnya: In-Sync Replica   Berikutnya: Topic Design →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact