Distributed Lock
Penguncian per-record untuk mencegah konflik penulisan bersamaan
Distributed Lock adalah mekanisme koordinasi antar worker process yang berjalan di cluster mode. Fitur ini menggunakan Redis sebagai backend dan dirancang untuk mengatasi race condition pada operasi WRITE terhadap record yang sama. Lock bersifat per-record sehingga operasi pada record yang berbeda tetap berjalan paralel.
Referensi Cepat (Quick Reference)
| Properti | Nilai |
|---|---|
| Dependency | Redis Server |
| Aktivasi | LOCK_DISTRIBUTED_ENABLED=true di file .env |
| Lock otomatis | updateData() dan deleteData() (per-record WRITE lock) |
| Strategi | retry (default, exponential backoff) atau reject (immediate fail) |
| Default TTL | 10 detik |
| Tanpa lock | addData() (INSERT membuat row baru) dan operasi READ |
Masalah yang Diselesaikan (Problem Statement)
Tanpa Distributed Lock:
Worker 1 → UPDATE supplier id='abc' SET nama='PT A' ─┐
Worker 2 → UPDATE supplier id='abc' SET nama='PT B' ─┘→ Hasil tidak konsisten
Dengan Distributed Lock (per-record):
Worker 1 → Lock(abc) → UPDATE → Release
Worker 2 → Tunggu Lock(abc) ─────────→ Lock acquired → UPDATE → ReleaseLock bersifat per-record sehingga operasi pada record berbeda berjalan paralel tanpa saling memblokir:
Worker 1 → UPDATE supplier id='abc' → Lock(abc) → Berjalan paralel
Worker 2 → UPDATE supplier id='xyz' → Lock(xyz) → Berjalan paralel
Worker 3 → UPDATE supplier id='abc' → Lock(abc) → Tunggu Worker 1 selesaiKonfigurasi (Configuration)
LOCK_DISTRIBUTED_ENABLED=true
LOCK_DISTRIBUTED_STRATEGY=retry
LOCK_DISTRIBUTED_TTL=10
LOCK_DISTRIBUTED_RETRY=3
LOCK_DISTRIBUTED_RETRY_DELAY=100| Parameter | Default | Keterangan |
|---|---|---|
LOCK_DISTRIBUTED_ENABLED | false | Mengaktifkan fitur distributed lock |
LOCK_DISTRIBUTED_STRATEGY | retry | retry (exponential backoff) atau reject (immediate fail) |
LOCK_DISTRIBUTED_TTL | 10 | Durasi maksimal lock aktif (detik) sebelum expire otomatis |
LOCK_DISTRIBUTED_RETRY | 3 | Jumlah percobaan acquire lock (hanya untuk strategy retry) |
LOCK_DISTRIBUTED_RETRY_DELAY | 100 | Delay awal antar retry dalam ms (hanya untuk strategy retry) |
Strategi Lock (Lock Strategies)
Strategy: retry (Default)
Request menunggu dengan exponential backoff sampai lock tersedia atau timeout tercapai. Delay antar percobaan: RETRY_DELAY * 2^attempt (default: 100ms, 200ms, 400ms).
Worker A → Lock(abc) acquired → UPDATE → Release
Worker B → Lock(abc) wait 100ms → wait 200ms → Lock acquired → UPDATE → Release
Worker C → Lock(abc) wait 100ms → wait 200ms → wait 400ms → TIMEOUT ERRORStrategy: reject
Request langsung ditolak jika lock tidak tersedia, tanpa menunggu. Parameter RETRY dan RETRY_DELAY diabaikan.
Worker A → Lock(abc) SET NX → OK → UPDATE → Release
Worker B → Lock(abc) SET NX → FAIL → IMMEDIATE ERRORPerbandingan Strategi (Strategy Comparison)
| Aspek | retry | reject |
|---|---|---|
| Saat lock tidak tersedia | Menunggu dan coba lagi | Langsung error |
| Latensi request kedua | Bertambah (waktu tunggu) | Tidak ada (langsung error) |
| Client handling | Tidak perlu retry logic | Perlu retry logic di client |
| Cocok untuk | Frontend/UI, operasi penting | Sistem otomatis dengan retry logic sendiri |
Operasi yang Dilindungi (Protected Operations)
| Method | Lock | Alasan |
|---|---|---|
updateData() | ✓ | WRITE lock per-record, melindungi concurrent update |
deleteData() | ✓ | WRITE lock per-record, melindungi concurrent update+delete |
addData() | ✗ | INSERT membuat row baru, tidak ada konflik pada record yang sama |
getDatatables() | ✗ | Operasi READ, database MVCC menjamin read consistency |
Format Lock Key
rf:lock:{project}:{endpoint}:{recordId}:writeContoh: rf:lock:mini-inventory:supplier:550e8400-...:write
Distributed lock dan cache layer adalah dua fitur yang independen. Keduanya menggunakan Redis sebagai backend, tetapi tidak saling bergantung. Lock dapat aktif tanpa cache, dan sebaliknya.
Langkah Selanjutnya (Next Steps)
- Cache untuk layer caching berbasis Redis
- Idempotency untuk proteksi duplikasi request
- Rate Limit untuk pembatasan jumlah request