Distributed Lock vs Message Queue (BullMQ, RabbitMQ) vs Kafka β€” Mengatasi Race Condition di Sistem Terdistribusi

πŸš€ Pendahuluan

Dalam sistem terdistribusi, dua masalah klasik yang sering muncul adalah:

  1. Race condition β€” dua node memodifikasi data yang sama dalam waktu bersamaan.

  2. Load tinggi β€” server harus membagi beban dengan mereplikasi proses ke banyak node.

Untuk mengatasi ini, developer biasanya mengenal teknologi seperti Redis Redlock, etcd, ZooKeeper, BullMQ, RabbitMQ, dan Kafka.
Namun, tidak semuanya punya peran yang sama.

Artikel ini menjelaskan perbedaan antara:

  • Distributed Lock System,

  • Message Queue System (BullMQ, RabbitMQ), dan

  • Event Streaming Platform (Kafka).


πŸ”’ 1. Distributed Lock β€” Mencegah Race Condition Langsung

Distributed lock digunakan untuk memastikan hanya satu proses atau node yang dapat mengubah data tertentu dalam satu waktu, meskipun sistem berjalan di banyak server.

🧠 Tujuan utama:

Menjamin eksklusivitas akses terhadap resource bersama untuk mencegah race condition.

βš™οΈ Cara Kerja Singkat

  • Server A membuat lock (misalnya kunci di Redis/etcd).

  • Server B yang mencoba mengakses data yang sama harus menunggu hingga lock dilepas.

  • Setelah Server A selesai, lock dihapus, dan server lain boleh melanjutkan.

Dengan begitu, hanya satu server di seluruh cluster yang dapat melakukan operasi write (menulis atau mengubah data) terhadap resource yang sama.

🧩 Contoh Tools Populer

Sistem

Keunggulan

Ekosistem

Redis (Redlock)

Simpel, cepat, mudah diintegrasikan

Web API, microservices

etcd

Konsistensi kuat, native di Kubernetes

Cluster management

ZooKeeper

Stabil dan battle-tested

Hadoop, Kafka cluster

Consul

Bisa juga untuk service discovery

HashiCorp ecosystem

πŸ’» Contoh Implementasi (Redis Redlock)

import { createClient } from 'redis';
import { Redlock } from 'redlock';

const client = createClient();
await client.connect();

const redlock = new Redlock([client]);

await redlock.using(['lock:balance:123'], 5000, async () => {
  // hanya satu proses di cluster yang bisa menjalankan kode ini
  await updateBalance();
});

πŸ“Œ Gunakan distributed lock ketika:

  • Kamu ingin memastikan hanya satu proses yang bisa memperbarui resource bersama (saldo, stok, transaksi).

  • Kamu punya sistem terdistribusi yang berjalan paralel di banyak server.


πŸ“¨ 2. Message Queue β€” Mengatur Antrian dan Distribusi Pekerjaan

Message queue system seperti BullMQ dan RabbitMQ digunakan untuk mengantri dan mendistribusikan pekerjaan secara asynchronous.

Mereka tidak melakukan locking terhadap resource, tetapi dapat mengurangi race condition secara tidak langsung dengan mengatur urutan eksekusi task. Message queue bekerja di level sistem terdistribusi (multi server).

🧠 Tujuannya:

Mengatur kapan dan bagaimana pekerjaan dieksekusi agar beban sistem terdistribusi dengan rapi.


πŸ‚ BullMQ (Redis-based)

BullMQ adalah message queue modern berbasis Redis, populer di ekosistem Node.js.
Ia memungkinkan pembuatan job queue, penjadwalan, dan retry mechanism.

import { Queue, Worker } from 'bullmq';

const emailQueue = new Queue('email');

// producer
await emailQueue.add('sendEmail', { to: 'user@example.com' });

// consumer
const worker = new Worker('email', job => sendEmail(job.data.to));

Kelebihan BullMQ:

  • Setup sederhana (cukup Redis).

  • Dukungan untuk delay, retry, dan concurrency.

  • Cocok untuk proyek Node.js kecil–menengah.


πŸ‡ RabbitMQ (AMQP-based)

RabbitMQ adalah broker pesan klasik berbasis protokol AMQP.
Konsepnya mirip BullMQ tapi lebih matang dan lintas bahasa.

// producer
channel.sendToQueue('email', Buffer.from(JSON.stringify({ to: 'user@example.com' })));

// consumer
channel.consume('email', msg => sendEmail(JSON.parse(msg.content)), { noAck: true });

Kelebihan RabbitMQ:

  • Stabil, mature, dan lintas bahasa (Node, Java, Python, Go).

  • Mendukung routing dan acknowledgment kompleks.

  • Cocok untuk sistem besar dengan beban tinggi.


🧩 Kesimpulan BullMQ & RabbitMQ

Aspek

BullMQ

RabbitMQ

Backend

Redis

AMQP protocol

Bahasa populer

Node.js

Multi-language

Fokus

Task queue ringan, delay, retry

Routing pesan kompleks

Gunakan ketika

Butuh job async sederhana

Butuh integrasi antar layanan besar


🌊 3. Kafka β€” Event Streaming Platform

Kafka berbeda dari queue biasa β€” ia adalah event log terdistribusi.
Kafka menyimpan event secara berurutan dan persisten sehingga bisa dibaca berulang oleh banyak konsumer.

🧠 Tujuan utama:

Menyimpan dan memutar ulang aliran event dalam jumlah besar secara real-time.

βš™οΈ Contoh Penggunaan

// producer
producer.send({ topic: 'user-events', messages: [{ value: 'UserRegistered' }] });

// consumer
consumer.subscribe({ topic: 'user-events' });
consumer.run({
  eachMessage: async ({ message }) => console.log(message.value.toString())
});

Kelebihan Kafka:

  • Throughput tinggi dan penyimpanan event durable.

  • Cocok untuk event sourcing, analitik, dan log streaming.

  • Dapat di-replay kapan pun.


βš–οΈ 4. Perbandingan Lengkap

Aspek

Distributed Lock (Redis, etcd)

BullMQ / RabbitMQ

Kafka

Tujuan utama

Mencegah banyak proses mengubah data yang sama

Menangani antrian & distribusi job

Menyimpan dan menyalurkan event

Mencegah race condition?

βœ… Ya, langsung

⚠️ Tidak langsung (urutan job)

⚠️ Tidak langsung

Skema kerja

Node rebutan kunci (lock/unlock)

Producer β†’ Queue β†’ Worker

Producer β†’ Topic β†’ Consumer

Throughput

Menengah

Tinggi

Sangat tinggi

Ketahanan data

Sementara (ephemeral)

Bisa diatur (persistent/volatile)

Persistent & replayable

Kapan digunakan

Update saldo, stok, resource bersama

Email, job async, load balancing

Event sourcing, log analitik


🧠 5. Kapan Digabung?

Dalam sistem berskala besar, ketiganya sering digunakan bersama:

πŸ“¦ Contoh arsitektur:

User API β†’ Queue (BullMQ / RabbitMQ) β†’ Worker β†’ Redis Lock β†’ Database β†’ Kafka
  • Queue mengatur antrian pekerjaan agar beban server merata.

  • Redis Lock memastikan hanya satu worker yang mengubah data tertentu dalam satu waktu.

  • Kafka menyimpan jejak semua transaksi untuk analisis real-time.

Hasilnya: cepat, aman, dan konsisten.


🧩 Kesimpulan

Sistem

Kategori

Fokus Utama

Cocok Untuk

Redis, etcd, ZooKeeper

Distributed Lock

Mengontrol siapa yang dapat mengubah data (eksklusif)

Mencegah race condition

BullMQ / RabbitMQ

Message Queue

Menjadwal & mendistribusikan pekerjaan

Asynchronous task handling

Kafka

Event Streaming

Merekam dan menyalurkan event

Analytics & event sourcing

πŸ”‘ Singkatnya:

  • Gunakan Distributed Lock untuk memastikan hanya satu proses yang boleh mengubah data tertentu dalam satu waktu.

  • Gunakan BullMQ/RabbitMQ untuk mengatur kapan dan bagaimana pekerjaan dijalankan.

  • Gunakan Kafka untuk mencatat apa yang terjadi di seluruh sistem.

Hey there πŸ‘‹

Ready to help you explore?