Distributed Commit Log #

Dalam dunia pemrosesan data real-time modern, kita sering kali dibenturkan pada dilema arsitektur klasik: bagaimana cara menyimpan jutaan event per detik secara andal tanpa membuat server kolaps akibat beban disk I/O yang ekstrem? Database relasional tradisional menjawab tantangan penyimpanan dengan struktur indeks yang rumit, namun arsitektur tersebut tidak dirancang untuk menangani beban throughput sekuensial berskala raksasa secara bersamaan. Di sinilah Distributed Commit Log masuk sebagai pilar pertahanan terkuat dan jantung dari arsitektur Apache Kafka. Kafka bukanlah database relasional tradisional dengan indeks dinamis; Kafka adalah log transaksi terdistribusi yang sangat sederhana namun memiliki performa luar biasa. Dengan memperlakukan data sebagai aliran catatan (stream of records) yang hanya bisa ditambahkan di akhir (append-only) dan tidak dapat diubah (immutable), Kafka berhasil membalikkan paradigma penyimpanan data terdistribusi. Memahami anatomi commit log, cara sistem operasi mengoptimalkan aliran biner ini melalui Page Cache dan Zero-Copy, serta perbedaannya dengan struktur database tradisional adalah langkah awal paling krusial untuk menguasai performa ekstrem Kafka dalam ekosistem aplikasi kita.


Anatomi dan Filosofi Append-Only Log #

Secara logis, commit log adalah salah satu struktur data paling sederhana dalam ilmu komputer: sebuah daftar record terurut secara kronologis yang hanya mengizinkan penulisan di ujung paling akhir (append-only). Kita tidak dapat menyisipkan data di tengah-tengah log, dan kita juga tidak dapat memperbarui data yang sudah tertulis. Sekali data masuk ke dalam log, statusnya menjadi absolut dan abadi (immutable).

Di dalam Kafka, setiap partisi dari suatu topik diwakili oleh satu unit commit log terdistribusi ini. Setiap event yang dikirim oleh produsen akan ditulis ke akhir log fisik ini dan langsung diberikan nomor identitas unik berupa integer 64-bit yang disebut offset. Offset ini bertindak sebagai penunjuk posisi absolut pesan di dalam partisi. Konsumen (consumer) membaca log ini secara berurutan dari kiri ke kanan (dari offset rendah ke offset tinggi) dengan memelihara koordinat pembacaannya sendiri. Karena konsumen tidak mengubah log saat membaca data, banyak konsumen dapat membaca log yang sama secara bersamaan tanpa saling mengganggu atau memblokir satu sama lain.

Pada tingkat sistem file disk fisik, commit log dipecah menjadi beberapa berkas fisik yang lebih kecil yang disebut Segment. Segmentasi ini dilakukan karena menulis seluruh data ke dalam satu berkas tunggal yang berukuran terabytes akan menyulitkan sistem operasi dalam hal manajemen ruang penyimpanan dan proses pembersihan data. Setiap segmen terdiri dari tiga file utama di dalam direktori partisi broker:

  1. .log — Berkas biner yang menyimpan konten event yang sebenarnya.
  2. .index — Berkas indeks posisi yang memetakan offset pesan ke posisi byte fisik di dalam file .log. Ini digunakan untuk mempercepat pencarian acak ketika konsumen meminta membaca dari offset tertentu.
  3. .timeindex — Berkas indeks berbasis waktu yang memetakan timestamp event ke nomor offset. Ini digunakan untuk pencarian data berdasarkan waktu pengiriman (misalnya, mencari data dari 2 jam yang lalu).

Hanya ada satu segmen yang aktif menerima penulisan data baru pada satu waktu, yang disebut Active Segment. Ketika berkas .log dari segmen aktif tersebut mencapai batas ukuran maksimum (biasanya dikonfigurasi melalui parameter log.segment.bytes sebesar 1 GB) atau batas waktu maksimum (log.roll.hours sebesar 7 hari), segmen tersebut akan ditutup menjadi bersifat read-only, dan Kafka akan membuka segmen aktif baru yang kosong.

Segmentasi fisik inilah yang memungkinkan Kafka menerapkan kebijakan retensi data secara sangat efisien. Ketika data kita melewati batas waktu retensi (misalnya lebih dari 7 hari), Kafka cukup menghapus file segmen read-only tertua dari disk secara langsung. Operasi penghapusan berkas seutuhnya di tingkat sistem operasi jauh lebih cepat dan murah dibandingkan dengan operasi database tradisional yang harus memindai tabel dan menghapus baris demi baris data secara acak yang memicu fragmentasi disk.


Kecepatan Log Linier: O(1) vs Indeks B-Tree #

Salah satu mitos terbesar dalam pengembangan perangkat lunak adalah bahwa media penyimpanan disk (HDD/SSD) selalu lambat dibandingkan dengan memori RAM. Hal ini hanya benar jika kita melakukan akses disk secara acak (random disk access). Namun, jika kita melakukan akses disk secara berurutan (sequential disk access), perilakunya berubah drastis. Penulisan sekuensial pada disk modern, bahkan pada HDD piringan tradisional, memiliki kecepatan yang hampir setara dengan memori RAM (mencapai ratusan megabytes per detik) karena head pembaca disk tidak perlu terus-menerus bergerak mencari sektor memori fisik yang tersebar acak.

Database relasional tradisional (seperti PostgreSQL atau MySQL) dirancang untuk mendukung kueri pencarian yang fleksibel dan pembaruan data secara dinamis. Untuk memfasilitasi hal ini, mereka menggunakan struktur data pohon seimbang yang kompleks, seperti B-Tree atau variannya. Ketika kita menyimpan data baru atau memperbarui baris data di database relasional, database tidak hanya menulis data tersebut ke disk, tetapi juga harus memperbarui struktur pohon indeks B-Tree. Operasi ini melibatkan pencarian simpul pohon (node traversal), pemisahan halaman memori yang penuh (page splitting), penyeimbangan ulang pohon (balancing), dan penulisan acak ke berbagai lokasi sektor disk. Kompleksitas waktu untuk operasi ini adalah $O(\log N)$ di mana $N$ adalah jumlah data.

Selain itu, untuk menjaga konsistensi data selama proses pembaruan ini, database harus menerapkan kunci penguncian tabel atau baris (table/row lock) yang memblokir thread pembacaan atau penulisan lainnya. Ketika ukuran tabel membengkak dari jutaan menjadi miliaran baris, kinerja penulisan database tradisional akan menurun secara eksponensial akibat degradasi indeks B-Tree ini.

Apache Kafka membalikkan pendekatan ini sepenuhnya dengan memperlakukan disk sebagai log transaksi linier murni. Karena Kafka menggunakan model append-only, penulisan event baru selalu terjadi di akhir berkas fisik secara berurutan. Broker tidak perlu mencari-cari lokasi simpul pohon atau menyeimbangkan indeks; broker cukup melakukan operasi append data biner ke akhir file deskriptor. Kompleksitas penulisan ke commit log Kafka adalah O(1) konstan. Tidak peduli apakah kita memiliki 10 Megabytes atau 10 Terabytes data di dalam broker, kecepatan untuk menulis satu pesan baru ke akhir log akan selalu sama cepatnya karena tidak dipengaruhi oleh ukuran dataset total ($N$). Tidak ada proses penguncian tabel, tidak ada page splitting, dan tidak ada degradasi performa seiring waktu.


Diagram Performa: Penulisan Log vs B-Tree #

Untuk memberikan visualisasi yang jelas, mari kita bandingkan kompleksitas alur kerja penulisan data pada struktur B-Tree database relasional yang kompleks dengan kesederhanaan operasi append-only pada commit log Kafka.

flowchart TD
    subgraph BTreeSection ["Operasi Database Tradisional (Indeks B-Tree)"]
        direction TB
        InputB["Event Baru"] --> SearchNode["1. Cari Lokasi Node (Traversal O(log N))"]
        SearchNode --> CheckSpace{"2. Apakah Halaman Penuh?"}
        CheckSpace -- "Ya (Overhead Tinggi)" --> PageSplit["3. Lakukan Page Splitting & Balancing"]
        CheckSpace -- Tidak --> WriteRandom["4. Tulis Acak (Random IO) ke Sektor Disk"]
        PageSplit --> LockTable["5. Lock Halaman/Tabel (Memblokir Thread Lain)"]
        LockTable --> WriteRandom
    end

    subgraph CommitLogSection ["Operasi Apache Kafka (Distributed Commit Log)"]
        direction TB
        InputLog["Event Baru"] --> GetOffset["1. Ambil Offset Berikutnya (Sekuensial)"]
        GetOffset --> AppendLog["2. Tulis Langsung ke Akhir File (Sequential Append O(1))"]
        AppendLog --> IPCache["3. Simpan di OS Page Cache (Memori Cepat)"]
    end

    style PageSplit fill:#ffdddd,stroke:#ff8888
    style LockTable fill:#ffdddd,stroke:#ff8888
    style AppendLog fill:#ddffdd,stroke:#88ff88
    style IPCache fill:#ddffdd,stroke:#88ff88

Dari diagram di atas, kita dapat melihat bahwa jalur eksekusi Kafka jauh lebih pendek dan langsung. Kafka menghilangkan semua beban komputasi tambahan yang biasanya memperlambat pemrosesan data pada database tradisional.


Efisiensi Maksimal: OS Page Cache dan Zero-Copy Transfer #

Untuk memaksimalkan throughput pengiriman dan pembacaan data, Kafka mengandalkan arsitektur sistem operasi (OS) secara sangat cerdas daripada mencoba membangun caching layer sendiri di dalam JVM heap memory.

Secara umum, aplikasi Java (JVM) cenderung mengalokasikan caching memori internal di dalam JVM heap. Namun, pendekatan caching internal JVM ini memiliki beberapa kelemahan fatal bagi sistem pemrosesan data berskala tinggi:

  1. Garbage Collection (GC) Overhead — Menyimpan gigabytes data di memori heap JVM akan memicu proses pembersihan sampah memori (garbage collection) yang sangat sering dan lama. Hal ini memicu fenomena GC pause (sistem membeku sesaat) yang merusak konsistensi latensi pengiriman pesan.
  2. Object Memory Footprint — Struktur objek Java di memori heap sangat boros ruang penyimpanan. Sebuah string sederhana atau byte array kecil dapat membengkak ukurannya hingga 2x hingga 4x lipat karena adanya header objek JVM dan metadata kelas internal.
  3. Double Copying — Menyimpan cache di memori JVM berarti data harus disalin dua kali: pertama kali dari sistem operasi ke buffer aplikasi JVM, dan kedua kali dari JVM kembali ke kernel sistem operasi saat dikirim ke jaringan.

Kafka memecahkan masalah ini dengan membuang cache internal JVM heap dan menggunakan OS Page Cache (cache halaman sistem operasi) secara langsung. Ketika produsen mengirim data ke broker Kafka, broker menulis data tersebut ke file menggunakan standard I/O API. Sistem operasi Linux secara otomatis menangani berkas tersebut dengan menyimpannya di memori RAM bebas yang diubah menjadi Page Cache.

Broker Kafka tidak perlu terburu-buru melakukan sinkronisasi paksa ke disk fisik (fsync()) untuk setiap pesan tunggal; Kafka membiarkan sistem operasi melakukan pembilasan data (dirty page flushing) ke piringan disk secara asinkron di latar belakang menggunakan thread kernel pdflush. Jika broker Kafka mengalami crash secara tiba-tiba, data kita yang berada di Page Cache tidak akan hilang karena memori Page Cache dikelola langsung oleh kernel sistem operasi, bukan oleh proses JVM Kafka yang mati. Selama sistem operasi Linux server kita tidak mengalami mati daya listrik total, data tetap aman tersimpan.

Saat konsumen datang meminta data dari offset tertentu, Kafka akan memeriksa apakah data tersebut masih berada di OS Page Cache. Jika ya, data akan langsung dibaca dari RAM super cepat tanpa perlu memicu operasi baca disk fisik (disk read).

Namun, optimasi terbesar Kafka terletak pada bagaimana data yang berada di Page Cache dikirimkan ke jaringan. Di sistem tradisional, pemindahan data dari Page Cache ke soket jaringan melibatkan proses penyalinan manual melalui User Space (aplikasi):

  1. Disk menyalin data ke OS Kernel Page Cache.
  2. Aplikasi (User Space) membaca data dari Page Cache ke buffer memori lokal aplikasi (JVM Heap).
  3. Aplikasi menulis data tersebut kembali ke Socket Buffer di Kernel Space.
  4. Kernel Space menyalin data dari Socket Buffer ke kartu jaringan (NIC Buffer).

Alur tradisional ini membutuhkan 4 kali operasi penyalinan data (data copy) dan 4 kali peralihan konteks sistem (context switch) antara User Space dan Kernel Space. Proses ini sangat memboroskan siklus CPU dan bandwidth memori RAM.

Apache Kafka memangkas rantai birokrasi ini dengan memanfaatkan fitur Zero-Copy Data Transfer melalui system call sendfile di Linux. Ketika konsumen meminta data, broker Kafka memanggil perintah sendfile di tingkat kernel. Perintah ini mengizinkan sistem operasi untuk menyalin data secara langsung dari Kernel Page Cache ke Buffer Kartu Jaringan (NIC Buffer) tanpa perlu menyalin data ke memori aplikasi JVM (User Space) terlebih dahulu.

Mari kita perhatikan perbandingan alur aliran data tradisional dengan optimasi Zero-Copy pada diagram berikut:

flowchart TD
    subgraph TraditionalFlow ["Aliran Data Tradisional (Tanpa Zero-Copy)"]
        direction TB
        DiskT["Disk Storage"] -->|"1. Copy ke Kernel Space"| CacheT["Kernel Page Cache"]
        CacheT -->|"2. Copy ke User Space"| JVMHeap["JVM Heap Memory (Aplikasi)"]
        JVMHeap -->|"3. Copy ke Kernel Socket Buffer"| SocketT["Socket Buffer"]
        SocketT -->|"4. Copy ke NIC Buffer"| NICT["NIC Buffer (Hardware)"]
    end

    subgraph ZeroCopyFlow ["Aliran Data Zero-Copy (sendfile)"]
        direction TB
        DiskZ["Disk Storage"] -->|"1. Copy ke Kernel Space"| CacheZ["Kernel Page Cache"]
        CacheZ -->|"2. Direct Transfer (Zero Copy)"| NICZ["NIC Buffer (Hardware)"]
    end

    style JVMHeap fill:#ffdddd,stroke:#ff8888
    style NICZ fill:#ddffdd,stroke:#88ff88

Dengan Zero-Copy, alurnya diringkas menjadi hanya 2 kali penyalinan data dan 2 kali context switch, serta sama sekali tidak menggunakan memori JVM heap atau memicu Garbage Collection. Inilah rahasia mengapa Kafka mampu menjenuhkan bandwidth jaringan ethernet gigabit server secara penuh dengan pemakaian CPU yang sangat minim.


Immutable Data Stream: Mengapa Kita Menolak Mutabilitas #

Dalam pengembangan aplikasi database relasional, status mutable (dapat diubah) adalah hal yang biasa kita lakukan sehari-hari. Kita memperbarui alamat pengguna, mengubah status transaksi dari PENDING menjadi SUCCESS, atau menghapus baris data yang dianggap tidak valid. Namun, dalam arsitektur sistem terdistribusi skala besar, mutabilitas adalah sumber utama terjadinya kompleksitas, balapan kondisi (race condition), dan ketidakkonsistenan data.

Mengapa Kafka bersikeras menolak mutabilitas dan menerapkan prinsip immutability (data tidak dapat diubah) pada commit log?

1. Bebas dari Masalah Ketenangan Lintas-Thread (Thread Safety) #

Karena data di dalam log bersifat immutable, tidak ada thread produsen atau konsumen yang dapat memodifikasi data yang sudah tertulis. Kita tidak memerlukan mekanisme penguncian memori (memory locking) atau kontrol transaksi konkurensi (MVCC) yang rumit saat membaca data. Ribuan konsumen dapat membaca area log yang sama secara bersamaan dengan kecepatan RAM maksimal tanpa khawatir data berubah di tengah jalan.

2. Replikasi Data Terdistribusi yang Konsisten #

Dalam kluster Kafka terdistribusi, data direplikasi dari broker Leader ke beberapa broker Follower. Karena log bersifat append-only dan immutable, proses replikasi menjadi sangat sederhana dan deterministik. Broker Follower cukup meminta data mulai dari offset terakhir yang mereka miliki. Broker Leader hanya perlu mengirimkan aliran byte baru secara berurutan. Tidak ada risiko di mana data di tengah-tengah log berubah di Leader sementara Follower masih menyimpan data lama (divergent state), yang biasanya merupakan mimpi buruk dalam sinkronisasi replikasi database relasional.

3. Audit Trail dan Kebenaran Tunggal (Single Source of Truth) #

Dalam sistem bisnis, kejadian (event) masa lalu adalah sejarah yang tidak bisa dirubah. Jika seorang pelanggan membeli barang di toko kita pada jam 10 pagi, itu adalah fakta sejarah. Jika pelanggan tersebut membatalkan pembelian pada jam 10:15 pagi, tindakan pembatalan tersebut tidak seharusnya menghapus record pembelian jam 10 pagi. Tindakan pembatalan adalah event baru yang terjadi di waktu yang baru. Dengan menyimpan seluruh fakta sejarah ini sebagai log append-only immutable, kita memiliki riwayat audit (audit trail) yang sempurna dan tidak dapat dimanipulasi.

4. Replayability (Kemampuan Putar Ulang Data) #

Immutabilitas log memungkinkan fitur terkuat di Kafka: Replayability. Karena log fisik tidak dihapus atau diubah setelah dibaca, konsumen dapat memutar kembali posisi pembacaannya (reset offset) ke awal log atau ke waktu tertentu di masa lalu. Ini sangat berguna ketika aplikasi kita mengalami bug atau crash, dan kita perlu membangun kembali status memori aplikasi dengan memproses ulang semua event bersejarah dari awal seolah-olah waktu diputar kembali.


Anti-pattern vs Solusi dalam Pola Pikir Append-Only #

Salah satu kesalahan mental terbesar yang sering dialami oleh developer baru saat mulai mengadopsi Apache Kafka adalah memperlakukan Kafka seperti database relasional (CRUD mindset). Mereka mencoba mencari cara untuk memperbarui pesan lama yang salah di dalam log partisi secara asinkron.

Kasus: Memperbarui Status Transaksi Pelanggan #

Bayangkan aplikasi kita mengelola pesanan e-commerce. Ketika status pesanan berubah dari ORDER_CREATED menjadi ORDER_SHIPPED, developer dengan CRUD mindset akan mencoba mengutak-atik Kafka untuk mengedit event lama di offset awal, atau membuat kueri khusus untuk mengubah nilai field status di dalam pesan yang sudah terkirim.

Konsekuensi Kegagalan: Apache Kafka sama sekali tidak menyediakan API untuk melakukan modifikasi atau penghapusan pesan berdasarkan offset tertentu secara acak. Upaya paksa untuk memodifikasi log disk secara langsung di luar sistem Kafka akan merusak struktur indeks .index dan .timeindex, memicu corruption error fatal pada broker, menghentikan proses replikasi, dan merusak konsistensi data konsumen yang mengandalkan urutan offset numerik yang linier.

Mari kita lihat perbedaan implementasi menggunakan bahasa Java antara pola pikir mutable yang salah dengan pola pikir immutable stream yang benar:

// =========================================================================
// ANTI-PATTERN: Pola Pikir Database Mutable (CRUD Mindset)
// Mencoba memperlakukan Kafka log seperti database yang barisnya bisa di-update.
// =========================================================================
public class OrderProcessorAntiPattern {
    public void processOrderUpdate(String orderId, String newStatus) {
        // ✗ JANGAN: Mencari cara untuk mencari offset pesan lama dan memodifikasi isinya di Kafka.
        // Kafka tidak mendukung operasi UPDATE secara acak.
        System.err.println("Error: Tidak ada API Kafka untuk update offset secara acak!");
        throw new UnsupportedOperationException("Kafka log is immutable!");
    }
}

// =========================================================================
// SOLUSI YANG BENAR: Pola Pikir Append-Only Immutable Stream
// Kita merepresentasikan perubahan status sebagai event baru yang ditambahkan di akhir log.
// Konsumen akan merekonstruksi status akhir dengan memproses urutan event secara kronologis.
// =========================================================================
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import java.util.Properties;

public class OrderProcessorSolution {
    private final KafkaProducer<String, String> producer;
    private final String topicName = "ecommerce-orders";

    public OrderProcessorSolution() {
        Properties props = new Properties();
        props.put("bootstrap.servers", "localhost:9092");
        props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        props.put("enable.idempotence", "true"); // Menjamin keandalan pengiriman
        
        this.producer = new KafkaProducer<>(props);
    }

    public void processOrderUpdate(String orderId, String newStatus) {
        // ✓ BENAR: Buat event baru yang menggambarkan fakta sejarah perubahan status
        // Event pertama: ORDER_CREATED (offset 100)
        // Event kedua:   ORDER_SHIPPED (offset 101) -> Ditambahkan di akhir log
        String eventPayload = String.format("{\"order_id\":\"%s\",\"status\":\"%s\",\"timestamp\":%d}", 
            orderId, newStatus, System.currentTimeMillis());
            
        ProducerRecord<String, String> record = new ProducerRecord<>(topicName, orderId, eventPayload);
        
        // Kirim event secara asinkron tanpa memblokir thread
        producer.send(record, (metadata, exception) -> {
            if (exception != null) {
                // Penanganan error jika transmisi gagal
                System.err.println("Gagal mengirim event update order: " + exception.getMessage());
            } else {
                // ✓ Berhasil menulis ke akhir commit log secara sekuensial O(1)
                System.out.printf("Sukses menulis event sekuensial ke topik %s, partisi %d, offset %d\n",
                    metadata.topic(), metadata.partition(), metadata.offset());
            }
        });
    }
}

Dengan mengadopsi pola pikir immutable stream di atas, konsumen yang membaca topik ecommerce-orders akan menerima dua event terpisah secara berurutan:

  1. ORDER_CREATED pada jam 10:00
  2. ORDER_SHIPPED pada jam 10:15

Konsumen cukup menyimpan status pesanan tersebut di database lokalnya sendiri (materialized view) dan melakukan pembaruan status di sana secara lokal. Di sisi Kafka, seluruh riwayat perubahan status terabdikan dengan sempurna dan aman dalam commit log.


Perbandingan Karakteristik: Commit Log vs Database Relasional #

Untuk memberikan gambaran yang lebih konkret, berikut adalah tabel perbandingan komprehensif antara karakteristik operasional distributed commit log Kafka dengan database relasional tradisional (RDBMS):

Karakteristik Distributed Commit Log (Kafka) Database Relasional (RDBMS)
Model Penulisan Append-only (selalu ditambahkan di akhir log fisik). In-place update (data ditimpa di lokasi fisik yang sama).
Kompleksitas Tulis $O(1)$ konstan, tidak dipengaruhi ukuran data. $O(\log N)$ karena perlu memperbarui indeks pohon B-Tree.
Immutabilitas Immutable (sekali ditulis tidak bisa diedit/dihapus). Mutable (mendukung penuh operasi UPDATE dan DELETE).
Mekanisme Caching Menggunakan OS Page Cache secara langsung. Menggunakan cache memori internal aplikasi (Buffer Pool).
Transfer Data Zero-Copy Transfer (sendfile memotong user space). Data disalin berulang kali dari kernel space ke user space JVM.
Akses Data Sequential read (konsumen memindai data secara berurutan). Random read (pencarian acak baris spesifik lewat indeks).
Model Konsumsi Pull model (konsumen menarik data sesuai offset). Kueri SQL interaktif secara real-time.
Kebijakan Retensi Berbasis segmen waktu/ukuran fisik berkas. Harus dihapus manual dengan kueri hapus terencana.

Ringkasan #

  • Definisi Commit Log — Commit log terdistribusi adalah struktur data linier append-only dan immutable di mana event baru selalu ditambahkan di akhir log fisik dan diberikan nomor identitas unik berupa offset.
  • Kompleksitas O(1) — Penulisan ke commit log Kafka memiliki kompleksitas O(1) konstan karena tidak menggunakan indeks dinamis B-Tree yang membutuhkan traverse pohon, balancing, atau penguncian tabel.
  • Segmentasi Log — Commit log partisi dibagi menjadi berkas-berkas fisik kecil bernama segmen (.log, .index, .timeindex) untuk mempermudah retensi data dan pembersihan disk.
  • OS Page Cache — Kafka membuang cache internal JVM heap dan memanfaatkan OS Page Cache secara langsung guna menghindari GC pauses dan double copying data di memori.
  • Optimasi Zero-Copy — Menggunakan system call sendfile untuk mengirim data langsung dari Page Cache kernel ke NIC buffer, memotong overhead penyalinan data ke User Space.
  • Prinsip Immutabilitas — Sifat log yang immutable menjamin sistem bebas dari race condition, menyederhanakan replikasi data terdistribusi, dan memfasilitasi audit trail historis yang kokoh.
  • Event Replayability — Immutabilitas log memungkinkan konsumen memutar kembali posisi offset untuk mengolah kembali event sejarah kapan saja tanpa merusak data asli.
  • Hindari CRUD Mindset — Jangan pernah merancang sistem dengan mencoba mengubah pesan di offset tertentu di tengah log; gunakan pola pikir immutable event streaming dengan menambahkan event perubahan baru ke akhir log.

← Sebelumnya: Cluster   Berikutnya: Overview →

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