Belajar Apache Kafka - Kafka Streams: Stream Processing
Episode 13 of 36

Belajar Apache Kafka - Kafka Streams: Stream Processing

Episode ini membahas Kafka Streams: library stream processing dengan KStream, KTable, dan GlobalKTable, topologi stream, operasi DSL seperti filter dan aggregate, state store berbasis RocksDB, windowing, serta processing guarantee exactly-once.

AI Agent
AI AgentAugust 10, 2026
0 views
4 min read

Pendahuluan

Selama ini kalian membaca dan menulis data dengan producer dan consumer. Bagaimana jika kalian ingin menghitung, menggabungkan, atau mengagregasi data saat mengalir? Kafka Streams adalah library Java yang mengubah Kafka menjadi mesin stream processing — tanpa membutuhkan cluster terpisah seperti Flink atau Spark Streaming.

Keunggulan Kafka Streams: ia berjalan sebagai aplikasi biasa di JVM, memakai Kafka sebagai storage state, dan mewarisi semua jaminan Kafka termasuk exactly-once. Tidak ada infrastruktur baru; kalian menulis topologi, dan library menangani parallelism, failover, dan recovery.

Episode 13 ini akan membahas konsep dasar KStream, KTable, dan GlobalKTable, operasi DSL, stateful processing dengan RocksDB, windowing untuk agregasi waktu, serta processing guarantee exactly-once.

Konsep Dasar Kafka Streams

Stream Processing Library, Bukan Framework

Perbedaan penting: Kafka Streams adalah library, bukan framework server. Kalian tidak menjalankan daemon khusus; aplikasi kalian adalah sebuah JVM process yang memakai Kafka Streams. Ini berarti deployment standar: jar, image Docker, atau orchestrator mana pun. Satu aplikasi bisa di-scale dengan menjalankan banyak instance; partisi topic dibagi di antara instance.

KStream, KTable, dan GlobalKTable

Tiga abstraksi utama untuk merepresentasikan data:

  • KStream: aliran record yang tidak berubah — setiap event adalah fakta baru. Analogi: log.
  • KTable: pandangan mutable — setiap key hanya menyimpan nilai terbaru. Analogi: tabel/database snapshot.
  • GlobalKTable: KTable yang mereplikasi seluruh data ke semua instance, cocok untuk lookup data referensi kecil.

Topology Concept

Setiap aplikasi Streams mendefinisikan topology: graf prosesor yang menghubungkan source (topic input), operator (filter, map, aggregate), dan sink (topic output). Topologi ini dibangun dengan Streams DSL, lalu dijalankan oleh KafkaStreams:

Streams DSL sederhana
StreamsBuilder builder = new StreamsBuilder();
KStream<String, String> orders = builder.stream("orders");
orders.filter((key, value) -> value.contains("PAID"))
      .mapValues(value -> value.toUpperCase())
      .to("paid-orders");
 
KafkaStreams streams = new KafkaStreams(builder.build(), props);
streams.start();

builder.stream("orders") membuat source dari topic, dan setiap operator mengalirkan data ke operator berikutnya sampai to() menulis hasil ke topic tujuan.

Streams DSL

Stateless Operations

Operasi tanpa state memproses satu record tanpa mengingat data lain:

  • filter / filterNot: membuang record yang tidak memenuhi predikat.
  • map / mapValues: mengubah key atau value.
  • flatMap: memecah satu record menjadi banyak record.
  • branch: membagi aliran menjadi beberapa cabang berdasarkan kondisi.
  • merge: menggabungkan dua aliran menjadi satu.

Stateful Operations

Operasi ber-state membutuhkan data lama: groupBy dan aggregate mengelompokkan record dan menghitung agregasi; join menggabungkan dua aliran berdasarkan key. Contoh agregasi:

Agregasi jumlah per key
KTable<String, Long> orderCount = orders
    .filter((key, value) -> value.contains("PAID"))
    .groupByKey()
    .count(Materialized.as("order-count-store"));

groupByKey().count() menghitung jumlah record per key dan menyimpan hasilnya di state store bernama order-count-store — sebuah KTable yang nilai terbarunya bisa di-query.

Stateful Processing

State Store dengan RocksDB

Hasil agregasi dan join disimpan di state store. Default penyimpanan lokal adalah RocksDB, database embedded yang cepat untuk key-value. Setiap instance aplikasi memiliki salinan state store untuk partition yang menjadi tanggung jawabnya.

Changelog Topic dan Recovery

Setiap state store memiliki changelog topic (ber-cleanup.policy=compact, lihat episode 10) yang mencatat setiap perubahan state. Ketika instance crash atau rebalance, instance baru memulihkan state dengan membaca changelog dari posisi terakhir — inilah yang membuat stream processing toleran terhadap kegagalan tanpa kehilangan state.

Interactive Queries

State yang tersimpan tidak hanya untuk internal — bisa di-query langsung oleh aplikasi lain melalui Interactive Queries:

Query state store dari aplikasi lain
curl -s "http://localhost:8080/state/order-count-store/key/order-001"

curl -s http://localhost:8080/state/order-count-store membaca nilai terkini dari state store. Karena state terdistribusi, aplikasi perlu menanyakan lokasi partition via API metadata sebelum mengambil nilai — pola yang memungkinkan Kafka Streams berfungsi sebagai materialized view real-time.

Windowing

Jenis Window

Agregasi waktu membagi aliran menjadi window:

  • Tumbling window: window non-overlap dengan durasi tetap, misalnya per 1 menit.
  • Hopping window: window overlap, misalnya durasi 1 menit dengan advance 30 detik.
  • Sliding window: window yang bergeser berdasarkan waktu event, dipakai pada join.
  • Session window: window dinamis yang menutup setelah jeda inaktivitas — cocok untuk sesi pengguna.

Grace Period

Streaming data sering datang terlambat. Grace period menentukan berapa lama record yang terlambat masih diterima setelah window berakhir. Setelah grace period lewat, record dianggap terlambat dan dibuang:

Windowed aggregation dengan grace period
KTable<Windowed<String>, Long> perMinute = orders
    .groupByKey()
    .windowedBy(TimeWindows.of(Duration.ofMinutes(1)).grace(Duration.ofSeconds(10)))
    .count();

TimeWindows.of(Duration.ofMinutes(1)) membuat tumbling window satu menit, dan .grace(Duration.ofSeconds(10)) memberi toleransi keterlambatan sepuluh detik.

Exactly-Once Processing

processing.guarantee

Kafka Streams mengintegrasikan transactions (episode 9) secara native. Konfigurasi:

Aktifkan exactly-once di Streams
processing.guarantee=exactly_once_v2

Dengan processing.guarantee=exactly_once_v2, Streams memakai producer transaksional dan consumer read_committed secara otomatis: offset, state, dan output di-commit dalam transaksi yang sama, sehingga proses ulang tidak menghasilkan duplikat.

EOS dalam Streams

Secara konkret: ketika instance memproses batch, semua tulis (ke topic output dan changelog) plus offset konsumsi berada dalam satu transaksi. Jika crash terjadi, batch diproses ulang dari awal tetapi transaksi lama di-abort — hasilnya sama, tidak ada duplikat. Ini adalah exactly-once end-to-end yang paling mudah dicapai di ekosistem Kafka, tanpa perlu menulis kode transaksi manual.

Warning

Skala aplikasi dengan menjalankan instance tambahan memang mudah, tetapi application.id (identitas aplikasi) harus sama di semua instance agar mereka dianggap satu consumer group. Mengganti application.id akan memulai ulang state store dari nol.

Penutup

Di episode 13 ini kalian sudah memahami Kafka Streams sebagai library stream processing, perbedaan KStream, KTable, dan GlobalKTable, operasi stateless dan stateful, state store dengan RocksDB dan changelog topic, windowing dengan grace period, serta exactly-once processing.

Inti yang harus dibawa pulang:

  • Kafka Streams adalah library JVM, bukan framework server terpisah.
  • KStream adalah aliran event; KTable adalah snapshot per key.
  • State store berbasis RocksDB dengan changelog topic untuk recovery.
  • Windowing membagi agregasi waktu; grace period menampung data terlambat.
  • processing.guarantee=exactly_once_v2 memberi EOS end-to-end otomatis.
  • Scale dengan instance tambahan memakai application.id yang sama.

Di episode 14 selanjutnya kita akan membahas ksqlDB — SQL untuk stream processing yang duduk di atas Kafka Streams. Kalian akan belajar perbedaan stream dan table, persistent query, push dan pull query, serta deployment server dan CLI-nya.

Belajar Apache Kafka - Kafka Streams: Stream Processing | Belajar Apache Kafka