Apache Kafka memandang data yang mengalir di dalamnya sebagai log kejadian (event log) yang hanya dapat ditambah, bukan sebagai antrean yang mengosongkan dirinya sendiri maupun tabel yang terus dimutakhirkan. Topik ini menjelaskan model log kejadian itu terlebih dahulu, kemudian membandingkannya dengan antrean pesan dan basis data, lalu menunjukkan alasan modelnya menentukan banyak perilaku Kafka di lapangan. Setelah membaca topik ini, perbedaan antara sistem yang menghapus pesan setelah diambil dan sistem yang menyimpannya untuk dibaca ulang dapat dinyatakan dengan tepat.
Log kejadian sebagai model data#
Kafka menyimpan pesan dalam bentuk log kejadian, yaitu urutan pesan yang hanya dapat ditambah di ujung dan tidak dapat disunting maupun dihapus satu per satu. Setiap pesan menempati satu posisi bernomor yang disebut offset, dan nomor posisi itu tetap berlaku selama pesannya tersimpan. Penulisan selalu terjadi di ujung log, sedangkan pembacaan dapat dimulai dari posisi mana pun tanpa mengubah isi log. Model ini dijalankan secara terdistribusi, sehingga satu log bisa saja terpecah ke beberapa server sekaligus.
Diagram berikut memperlihatkan perbedaan perilaku pada situasi yang sama, yaitu dua consumer (aplikasi pembaca pesan) membaca tiga pesan. Pada antrean pesan, setiap pesan diberikan kepada satu consumer dan langsung dihapus. Pada log kejadian, kedua consumer membaca dari posisinya masing-masing, sedangkan isi log tetap utuh.
Offset bersifat permanen, sehingga sebuah consumer dapat berhenti dan dijalankan ulang, lalu melanjutkan pembacaan dari posisi semula. Broker (server Kafka) menyimpan pesan sesuai periode retensi yang ditetapkan, misalnya tujuh hari, tanpa memandang apakah pesan itu sudah dibaca atau belum. Sifat-sifat tersebut menjadikan Kafka lebih mirip arsip berurutan yang dapat dibaca ulang daripada angkutan pesan yang mengosongkan dirinya.
Perbedaan dengan antrean pesan#
Antrean pesan tradisional memperlakukan satu pesan sebagai satu pekerjaan yang hanya boleh dikerjakan sekali. Consumer yang mengambil pesan dari kepala antrean memicu penghapusannya, sehingga dua consumer pada antrean yang sama saling membagi pekerjaan dan tidak ada yang membaca seluruh isi. Model ini tepat untuk antrean tugas yang tidak perlu diulang, tetapi menghilangkan kemampuan membaca ulang pesan yang sudah diambil.
Demo berikut mensimulasikan kedua model dengan Python murni tanpa broker. Sebuah antrean diisi tiga pesanan dan dibaca oleh dua consumer, kemudian log dengan isi yang sama dibaca dari posisi yang berbeda.
# Simulasi dua model data: antrean yang menghapus pesan dan log yang menyimpannya.
PESAN = ["pesanan-101", "pesanan-102", "pesanan-103"]
def jalankan_antrean():
print("model antrean: pesan dihapus begitu diambil")
antrean = list(PESAN)
for nama in ("consumer A", "consumer B"):
print(f"{nama} mengambil {antrean.pop(0)}")
print(f"isian antrean tersisa: {antrean}")
def jalankan_log():
print("model log: pesan tetap ada, pembacaan bergerak lewat offset")
log = list(PESAN)
posisi_awal = {"consumer A": 0, "consumer B": 1}
for nama, offset in posisi_awal.items():
while offset < len(log):
print(f"{nama} membaca offset {offset}: {log[offset]}")
offset += 1
print(f"isian log tersisa: {log}")
jalankan_antrean()
jalankan_log()model antrean: pesan dihapus begitu diambil
consumer A mengambil pesanan-101
consumer B mengambil pesanan-102
isian antrean tersisa: ['pesanan-103']
model log: pesan tetap ada, pembacaan bergerak lewat offset
consumer A membaca offset 0: pesanan-101
consumer A membaca offset 1: pesanan-102
consumer A membaca offset 2: pesanan-103
consumer B membaca offset 1: pesanan-102
consumer B membaca offset 2: pesanan-103
isian log tersisa: ['pesanan-101', 'pesanan-102', 'pesanan-103']Keluaran memperlihatkan perbedaan yang menentukan. Pada antrean, consumer A mengambil pesanan-101 dan consumer B mengambil pesanan-102, sehingga tidak ada satu consumer pun yang membaca semua pesan. Pada log, consumer A membaca seluruh urutan mulai dari offset 0, sedangkan consumer B melompat ke offset 1 dan membaca sisanya. Baris terakhir menegaskan bahwa isi log tetap utuh karena pembacaan tidak menghapus apa pun.
Perbedaan dengan basis data#
Basis data relasional menyimpan keadaan terkini dan mengizinkan perubahan data melalui perintah pembaruan, sedangkan log kejadian menyimpan sejarah kejadian yang tidak dapat diubah. Kafka tidak menyediakan bahasa kueri, indeks berdasarkan nilai pesan, maupun penggabungan antar tabel, sehingga pencarian acak atas isi pesan bukan pekerjaan Kafka. Meskipun begitu, pesan tersimpan di diska dan bertahan sesuai retensi, sehingga peran Kafka sebagai tempat penyimpanan tetap nyata. Tabel berikut merangkum perbedaan antrean pesan, basis data, dan log kejadian Kafka.
| Aspek | Antrean pesan | Basis data | Log kejadian Kafka |
|---|---|---|---|
| Nasib pesan setelah dibaca | Dihapus | Tetap ada | Tetap ada sesuai retensi |
| Model data | Pekerjaan tunggal | Keadaan terkini | Sejarah kejadian |
| Cara mengakses | Mengambil dari kepala antrean | Kueri bebas | Membaca berurutan per partisi |
| Mengubah data lama | Tidak ada datanya | Dapat diubah | Tidak dapat diubah |
Perbedaan itu menjelaskan posisi Kafka dalam arsitektur sistem. Kafka mengalirkan sejarah kejadian dari sistem sumber ke banyak pembaca, sedangkan basis data menerima keadaan terkini yang dihitung dari sejarah tersebut. Keduanya saling melengkapi, dan pemilihan tempat penyimpanan bergantung pada pertanyaan yang ingin dijawab.
Mengapa model log penting#
Model log memisahkan waktu penulisan pesan dari waktu pembacaannya. Producer menulis pesan dan langsung berlanjut tanpa menunggu consumer siap, sedangkan consumer baru yang muncul beberapa jam kemudian tetap dapat membaca seluruh pesan sejak offset 0 selama retensi topic (kategori pesan) belum habis. Aplikasi yang gagal juga dapat diputar ulang (replay), yaitu membaca kembali urutan pesan lama untuk menghitung ulang hasilnya.
Contoh sederhananya adalah pencatatan suhu ruangan. Topic menerima pengukuran dari producer setiap menit, dan tiga aplikasi berbeda membaca topic yang sama untuk tiga tujuan berbeda, yaitu papan status, peringatan batas suhu, dan rekap harian. Ketiganya membaca data yang sama dari posisi masing-masing tanpa saling mengganggu. Perilaku semacam ini tidak dapat dicapai oleh antrean yang menghapus pesan setelah diambil, dan itulah alasan model log dipilih sebagai dasar Kafka.
Kesalahan umum#
Dua kesalahan berikut muncul ketika model log belum terpahami sepenuhnya. Keduanya berakar pada kebiasaan yang dibawa dari antrean pesan.
- Menganggap pesan hilang setelah dibaca. Consumer yang sudah membaca seluruh topic kadang dianggap membersihkan isinya, padahal penghapusan hanya diatur oleh retensi. Akibatnya, consumer baru yang membaca dari awal menemukan data lama yang tidak diharapkan. Perbaikannya adalah mengatur
retention.msatauretention.bytespada topic bila data lama memang perlu disingkirkan. - Menggunakan Kafka untuk pencarian acak atas isi pesan. Kafka menyimpan data tetapi tidak menyediakan kueri, sehingga kebutuhan pencarian dikerjakan sistem lain. Perbaikannya adalah menyalin data ke basis data atau mesin pencarian yang mendukung kueri, dengan Kafka tetap menjadi sumber sejarahnya.
Ringkasan#
- Kafka menyimpan pesan sebagai log kejadian yang hanya dapat ditambah, dan setiap pesan menempati posisi offset yang tetap.
- Antrean menghapus pesan setelah diambil, sedangkan log menyimpannya sehingga banyak consumer membaca secara independen.
- Kafka bukan pengganti basis data karena tidak menyediakan kueri, tetapi menyimpan sejarah kejadian di diska sesuai retensi, dan sejarah itu dapat dibaca ulang.
Referensi#
- Apache Kafka documentation — Apache Software Foundation — dokumentasi resmi yang menetapkan model data Kafka sebagai log yang terdistribusi, terpartisi, dan tereplikasi.
- Introduction — Apache Software Foundation — pengantar resmi yang membandingkan sistem perpesanan konvensional dengan model log kejadian Kafka.