Kafka Pattern Untuk Production

Pattern 1: Exactly-Once Semantics (Menjamin Kebenaran Data)

Tujuan utama pola ini adalah mengeliminasi kegagalan kebenaran (correctness failures), seperti pesan ganda (duplikasi) dan race conditions (kondisi balapan).

1.1 Layer 1: Idempotent Producer

Secara default, jika terjadi network timeout setelah pesan terkirim namun sebelum acknowledgment diterima, producer akan mengirim ulang pesan tersebut, sehingga menyebabkan duplikasi.

Solusi: Aktifkan idempotence. Kafka akan menyematkan sequence number pada setiap pesan, sehingga broker bisa mendeteksi dan menolak duplikasi secara otomatis.

Implementasi franz-go:

Library franz-go mengaktifkan idempotence secara default.

package main

import (
	"github.com/twmb/franz-go/pkg/kgo"
)

func NewProductionProducer() (*kgo.Client, error) {
	client, err := kgo.NewClient(
		kgo.SeedBrokers("localhost:9092"),
		// Idempotence is enabled by default.
		// Menjamin message tidak berubah urutan / tidak duplicate, khususnya saat retry

		// Menjamin durabilitas data (menunggu semua replika in-sync)
		kgo.RequiredAcks(kgo.AllISRAcks()),
	)
	return client, err
}

1.2 Layer 2: Partition Key Strategy

Tanpa partition key, pesan akan disebar secara acak (round-robin), menyebabkan hilangnya urutan (ordering). Ini memicu race conditions jika dua event terkait (misal: "Order Created" dan "Payment Success") diproses oleh consumer berbeda secara bersamaan.

Solusi: Gunakan Partition Key yang konsisten (misalnya OrderID). Ini menjamin semua pesan dengan ID yang sama masuk ke partisi yang sama dan diproses berurutan oleh satu consumer.

Implementasi franz-go:

1.3 Layer 3 & 4: Transactional Semantics & App-Level Idempotency

Lapisan infrastruktur (Layer 1 & 2) tidak bisa mencegah duplikasi jika consumer crash setelah memproses pesan tapi sebelum commit offset.

Solusi:

  1. Transactions: Menjamin pembacaan dan penulisan ke Kafka bersifat atomik.

  2. App-Level Idempotency: Consumer harus mengecek apakah pesan sudah pernah diproses (misal cek ke DB) sebelum mengeksekusi logika bisnis.

Implementasi franz-go (Transactional):


Pattern 2: Throughput Optimization (Optimalisasi Performa)

Kafka default dioptimalkan untuk latensi rendah (kirim secepatnya), yang justru membunuh throughput pada beban tinggi karena terlalu banyak network round-trips.

2.1 Layer 1: Producer Batching

Alih-alih mengirim pesan satu per satu, kumpulkan pesan dalam memori (batch) dan kirim sekaligus.

Konfigurasi:

  • batch.size: Ukuran batch dalam bytes.

  • linger.ms: Waktu tunggu maksimal sebelum batch dikirim (meski belum penuh)13131313.

2.2 Layer 2: Compression

Untuk Mengurangi beban bandwidth jaringan. Algoritma lz4 direkomendasikan karena keseimbangan terbaik antara rasio kompresi dan beban CPU.

Implementasi franz-go (Batching & Compression):

2.3 Layer 3: Consumer Fetch Optimization

Optimalkan cara consumer mengambil data. Jangan mengambil data byte demi byte. Paksa consumer menunggu sampai data cukup banyak terkumpul di broker sebelum dikirim melalui jaringan.

Implementasi franz-go:


Pattern 3: Failure Recovery (Ketahanan & Pemulihan)

Fitur auto-commit pada Kafka bekerja berdasarkan waktu (time-based), bukan penyelesaian tugas. Ini berbahaya karena bisa menyebabkan data hilang (jika crash setelah commit tapi sebelum proses selesai) atau duplikasi.

3.1 Manual Commit Strategy

Matikan auto-commit. Lakukan commit offset hanya setelah logika bisnis sukses dieksekusi sepenuhnya.

Implementasi franz-go:

3.2 Static Group Membership

Saat consumer restart (misal saat deploy), Kafka biasanya memicu Rebalance (stop-the-world) yang menghentikan seluruh grup consumer selama beberapa detik.

Solusi: Gunakan Static Group Membership. Dengan memberikan ID statis, Kafka akan menoleransi ketidakhadiran consumer sementara (selama session.timeout.ms) tanpa memicu rebalance.

Implementasi franz-go:


Direkomendasikan untuk menerapkan pola ini secara bertahap:

  1. Correctness (Pattern 1): Wajib. Data yang salah tidak ada gunanya diproses cepat.

  2. Performance (Pattern 2): Terapkan saat volume data mulai meningkat.

  3. Resilience (Pattern 3): Terapkan untuk stabilitas operasional jangka panjang.


Studi Kasus: "TicketMaster Lite" – High-Concurrency Concert Booking System

Skenario: Anda sedang membangun backend untuk penjualan tiket konser artis papan atas (misal: Coldplay atau Taylor Swift).

  • Masalah: Ribuan pengguna menekan tombol "Beli" secara bersamaan ("War Tiket").

  • Risiko:

    1. Overselling: Menjual tiket lebih dari kapasitas kursi (Race Condition).

    2. Double Charge: Pengguna tidak sengaja ter-charge 2x karena menekan tombol berulang saat jaringan lambat (Idempotency failure).

    3. System Crash: Server down karena beban mendadak dan pemulihan yang lama (Resilience failure).

Tech Stack:

  • Language: Golang 1.23+

  • Web Framework: Go Chi (Lightweight & Fast)

  • Database: PostgreSQL (dengan pgx driver)

  • Message Broker: Kafka (dengan github.com/twmb/franz-go)

Last updated