Message queue vs pub/sub; log (Kafka) vs broker (RabbitMQ)
Kenapa sebagian pekerjaan sebaiknya tidak ditunggu, dua cara mengantar pesan, dan dua keluarga produk yang paling sering disebut di interview
Sebelumnya, lesson 0015 menutup modul Caching: cache mengurangi kerja yang berulang. Modul Asinkron membahas kerja yang tidak perlu ditunggu. Lesson ini memberi kosakata dasarnya: queue, pub/sub, consumer group, log, dan broker.
1. Kenapa asinkron
Bayangkan endpoint checkout yang, setelah menyimpan pesanan, memanggil layanan email secara sinkron. Kalau layanan email butuh 5 detik, user menunggu 5 detik untuk sesuatu yang tidak ia lihat. Kalau layanan email mati, checkout ikut gagal. Message queue memutus ketergantungan ini: checkout menaruh pesan "kirim email untuk order 42" lalu langsung menjawab user, dan worker di belakang mengambil pesan itu kapan pun ia siap. Azure Architecture Center merangkumnya: message queue "decouple senders from consumers and prevent the sender from blocking a process while it waits for a response." [1]
Tiga istilah dasar: producer mengirim pesan, broker (server queue) menyimpannya, consumer mengambil dan memprosesnya. Yang dibeli dengan asinkron adalah waktu respons dan isolasi kegagalan; yang dibayar adalah komponen baru, hasil yang tidak langsung terlihat, dan pertanyaan baru: bagaimana kalau pesan hilang atau datang dua kali (lesson 0017).
2. Message queue vs pub/sub
Dua pola pengantaran ini sering tertukar. Bedanya ada pada berapa penerima per pesan.
| Message queue (point-to-point) | Pub/sub | |
|---|---|---|
| Penerima per pesan | Satu consumer; consumer lain mengambil pesan berikutnya | Setiap subscriber mendapat salinan |
| Dipakai untuk | Membagi kerja: kirim email, resize gambar, generate PDF | Memberi tahu banyak pihak: OrderPlaced ke email, stok, analitik |
| Menambah consumer berarti | Throughput naik (kerja dibagi) | Satu penerima baru, tanpa mengubah publisher |
Queue dengan banyak consumer disebut competing consumers: sistem harus memastikan "each message is delivered to only one consumer." [2] Pub/sub punya "a mechanism for copying each message from the input channel to the output channels for all subscribers interested in that message." [1] Satu catatan penting untuk keduanya: urutan penerimaan "isn't guaranteed" kecuali broker mendukung urutan per partition atau session. [1]
Latihan 1 — Queue atau pub/sub
Jawab tanpa scroll ke atas. Soal yang sama akan muncul lagi, diacak, di review 0026.
Kuis di lesson ini adalah feedback cepat, bukan bukti penguasaan; yang dicatat hanya hasil review 0026.
3. Log (Kafka) vs broker (RabbitMQ)
Di interview, "pakai queue" biasanya disusul "Kafka atau RabbitMQ?". Keduanya bisa melakukan queue dan pub/sub, tapi model penyimpanannya berbeda.
Kafka: log yang dipartisi
- Topik dan partition. Event disimpan di topic, dan topik dipecah menjadi beberapa partition di broker yang berbeda. Event dengan key yang sama (mis. customer ID) masuk ke partition yang sama, dan Kafka menjamin consumer membaca satu partition "in exactly the same order as they were written." [3]
- Tidak dihapus setelah dibaca. "Unlike traditional messaging systems, events are not deleted after consumption." Lama penyimpanan diatur per topik (retention), jadi consumer baru bisa membaca riwayat. [3]
- Consumer group. Setiap partition "is consumed by exactly one consumer within each subscribing consumer group at any given time." Posisi consumer cukup satu angka per partition, yaitu offset, dan consumer bisa "deliberately rewind back to an old offset and re-consume data." [4]
Konsekuensinya: di dalam satu group, Kafka bersifat queue (setiap partition dikerjakan satu instance), sedangkan antar-group, Kafka bersifat pub/sub (group billing dan group analytics masing-masing membaca semua event).
Jumlah partition adalah batas paralelisme satu group: 6 partition dengan 8 instance berarti 2 instance menganggur.
RabbitMQ: broker dengan exchange dan queue
- Exchange, binding, queue. Producer mengirim ke exchange, yang "distribute message copies to queues using rules called bindings." Fanout exchange mengirim salinan ke semua queue yang terikat (pub/sub); direct exchange memakai routing key yang cocok. [5]
- Dihapus setelah ack. Dengan acknowledgement, broker "will only completely remove a message from a queue when it receives a notification for that message." Setelah itu pesan tidak bisa dibaca ulang. [5]
| Kafka (log) | RabbitMQ (broker AMQP) | |
|---|---|---|
| Setelah dibaca | Tetap tersimpan sampai retention habis | Dihapus setelah ack |
| Baca ulang / consumer baru membaca riwayat | Ya, mundurkan offset | Tidak (pesan sudah hilang) |
| Urutan | Per partition (pilih key dengan hati-hati) | Per queue, selama satu consumer |
| Routing | Sederhana: topik + key | Fleksibel: exchange direct/fanout/topic/headers |
| Cocok untuk | Event stream throughput tinggi, beberapa tim membaca event yang sama, replay | Job queue, routing per tipe pesan, pola request/reply |
Redis Pub/Sub juga sering disebut, tapi semantiknya "at-most-once": kalau subscriber terputus, "the message is forever lost." Cocok untuk notifikasi yang boleh hilang, bukan untuk pesanan. [6]
Latihan 2 — Kafka, RabbitMQ, consumer group
Jawab tanpa scroll ke atas. Soal yang sama akan muncul lagi, diacak, di review 0026.
4. Kapan tidak perlu
Sinyal yang membenarkan queue: pekerjaan yang lambat (detik, bukan milidetik) atau bergantung pada layanan pihak ketiga yang tidak stabil, dan hasilnya tidak dibutuhkan user saat itu juga; lonjakan beban yang melebihi kapasitas downstream (lesson 0018); atau satu event yang harus diterima beberapa layanan dari tim berbeda. Ukur dulu: berapa p99 bagian yang ingin dipindah, dan seberapa sering layanan itu gagal.
Biaya dan risiko: satu komponen lagi untuk dijalankan, dipantau, dan di-upgrade (cluster Kafka bukan barang kecil); hasil yang tidak langsung konsisten; duplikat dan pesan gagal yang harus ditangani (lesson 0017); dan debugging yang lebih sulit karena tidak ada satu call stack dari request sampai efek.
Alternatif lebih murah:
- Tetap sinkron kalau user butuh jawabannya sekarang dan layanan tujuan cepat. Jangan pecah sesuatu yang sudah cukup cepat.
- Tabel database sebagai job queue. Untuk beberapa ratus job per menit, tabel
jobsdengan worker yang mengambil baris memakaiSELECT … FOR UPDATE SKIP LOCKEDsering cukup. PostgreSQL menyebutSKIP LOCKED"can be used to avoid lock contention with multiple consumers accessing a queue-like table." [7] Bonusnya: job ditulis dalam transaksi yang sama dengan data bisnis. - Queue terkelola (mis. Amazon SQS) sebelum menjalankan cluster Kafka sendiri, kalau Anda tidak butuh replay atau throughput event stream.
Latihan lisan — Ucapkan dengan suara keras
Pasang timer dan jawab dengan suara keras, seolah sedang interview. Jangan buka jawaban contoh sebelum selesai.
"Kapan Anda memakai message queue, kapan pub/sub? Kapan Kafka dan kapan RabbitMQ? Dan kapan Anda tidak memakai keduanya?" (60 detik)
Bandingkan dengan jawaban contoh dan checklist-nya
"Asinkron saya pakai kalau pemanggil tidak butuh hasilnya sekarang, misalnya kirim email atau resize gambar, supaya request utama tidak menunggu. Kalau satu pekerjaan cukup dikerjakan satu worker, saya pakai queue dengan competing consumers. Kalau satu event harus diterima beberapa layanan, misalnya OrderPlaced ke email, stok, dan analitik, saya pakai pub/sub supaya masing-masing dapat salinan. Kafka saya pilih kalau butuh log yang bisa dibaca ulang, throughput tinggi, dan urutan per key; paralelismenya dibatasi jumlah partition per consumer group. RabbitMQ saya pilih untuk routing fleksibel lewat exchange dan binding, dengan pesan dihapus setelah ack. Tapi untuk beberapa ratus job per menit, tabel database dengan SELECT FOR UPDATE SKIP LOCKED sering cukup, dan kalau user butuh jawaban sekarang, panggilan sinkron tetap yang paling sederhana."
Checklist: apakah Anda menyebut…
- Alasan asinkron: pemanggil tidak menunggu pekerjaan yang boleh selesai belakangan
- Queue = satu pesan ke satu consumer (competing consumers)
- Pub/sub = setiap subscriber mendapat salinan pesan
- Kafka: log dengan retention, baca ulang lewat offset, urutan per partition/key
- RabbitMQ: exchange + binding untuk routing, pesan dihapus setelah ack
- Membenarkan komponen dengan angka, atau menyebut alternatif lebih murah (tabel DB, panggilan sinkron)
Lulus jika minimal 4 dari 6.
Berikutnya, lesson 0017: pesan bisa hilang atau datang dua kali. At-most-once, at-least-once, exactly-once, dan idempotency key.
Istilah: GLOSSARY.md (bagian "Asinkron") · Indeks: semua lesson System Design
Ada yang belum jelas? Tanyakan ke saya (agent) di terminal, misalnya: "Kenapa Kafka membatasi satu consumer per partition dalam satu group?", "Bandingkan SQS dengan RabbitMQ untuk job queue kecil."
Sumber: [1] Azure Architecture Center: Publisher-Subscriber pattern · [2] Azure Architecture Center: Competing Consumers pattern · [3] Apache Kafka 4.4 docs: Introduction · [4] Apache Kafka 4.4 docs: Design · [5] RabbitMQ: AMQP 0-9-1 Model Explained · [6] Redis docs: Pub/Sub · [7] PostgreSQL docs: SELECT (locking clause)