Sesi 12: Stateless adalah Syarat: Mengapa Redis Bukan Sekadar Cache
Bayangkan jika kamu login di loket 1, lalu pindah ke loket 2 dan petugas loket 2 sama sekali tidak mengenalimu. Siapa yang salah — kamu, atau desain loketnya?
1. Masalah Utama: "Stateful" Menghancurkan Horizontal Scaling
Horizontal scaling mengasumsikan bahwa semua instance server identik dan bisa digantikan kapan saja.
Tetapi jika aplikasi menyimpan data status user (state) di memori lokal proses (RAM server itu sendiri):
- User login di Server A ──► Session tersimpan di RAM Server A.
- Request kedua diarahkan oleh Load Balancer ke Server B ──► Server B tidak punya session itu ──► User ditendang keluar (HTTP 401 Unauthorized).
┌──────────────┐
│ Load Balancer│
└──────┬───────┘
Request 1 │ Request 2
(Login) │ (Checkout)
┌─────────┴─────────┐
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Server A │ │ Server B │
│ [RAM: User1]│ │ [RAM: Kosong│
│ LOGIN OK │ │ 401 ERROR! │
└─────────────┘ └─────────────┘
Untuk mengatasi ini, arsitek pemula tergoda menggunakan Sticky Session (Sesi 10). Tapi seperti yang kita pelajari, sticky session menciptakan Single Point of Failure dan merusak autoscaling.
2. Definisi Arsitektur Stateless
Aplikasi disebut Stateless jika: 1. Tidak ada data transaksi atau user session yang disimpan di disk lokal atau RAM server aplikasi. 2. Setiap instance aplikasi bisa mati, restart, atau diganti detik ini juga tanpa ada satu pun user yang terputus atau kehilangan keranjang belanjanya. 3. Server aplikasi hanya bertindak sebagai alat pemroses logika (Compute Engine murni).
Data status disimpan di lapisan penyimpanan bersama terpusat: Shared State Layer (Redis).
3. Redis Muncul: Bukan Cuma "Cache", Tapi Shared State Store
Banyak orang mengira Redis hanya untuk "membuat query lambat jadi cepat" (caching). Peran sebenarnya dalam arsitektur terdistribusi jauh lebih fundamental: menjadi sumber kebenaran status sesi (Session Store) dan koordinasi lintas server.
┌──────────────┐
│ Load Balancer│
└──────┬───────┘
┌───────────┴───────────┐
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Server A │ │ Server B │
│ (Stateless) │ │ (Stateless) │
└──────┬──────┘ └──────┬──────┘
│ │
└───────────┬───────────┘
▼
┌──────────────┐
│ Redis Shared │
│ Session Store│
└──────────────┘
Karakteristik Session Store di Redis:
- In-Memory Speed: Latensi sub-milidetik (< 1 ms), tidak membebani database SQL.
- TTL Otomatis (Time-To-Live): Data sesi otomatis terhapus saat expired (
EXPIRE session:123 3600) tanpa perlu cronjob pembersih manual. - Data Structure Lengkap: String, Hash (untuk user attributes), Set (untuk active tokens).
4. Distributed Lock: Menghindari Double-Execution
Ketika ada 10 server aplikasi yang berjalan paralel, apa yang terjadi jika dua request dari user yang sama masuk di milidetik yang sama (misal user menekan tombol "Bayar Sekarang" dua kali)?
Jika tidak ada mekanisme kunci terdistribusi (Distributed Lock), kedua server akan sama-sama memotong saldo user!
Mekanisme Redis Lock (SETNX / Redlock):
# Server A mencoba mengambil lock
acquired = redis.set("lock:order:user_123", "server_a", nx=True, ex=10)
if acquired:
try:
# Proses pembayaran...
potong_saldo()
kirim_barang()
finally:
# Lepas lock
redis.delete("lock:order:user_123")
else:
# Server B ditolak karena lock sedang dipegang Server A
return "Transaksi sedang diproses, mohon tunggu."
nx=True(Not Exists): Hanya berhasil jika kunci belum ada.ex=10(Expire 10s): Jika Server A mendadak mati (crash/OOM) saat memproses, kunci otomatis lepas setelah 10 detik agar tidak deadlock permanen.
5. Idempotency: Jaring Pengaman Terakhir
Bahkan dengan lock dan Redis, jaringan internet tidak pernah sempurna. Klien bisa saja mengirim ulang request yang sama karena timeout jaringan (retry).
Idempotency Key:
- Klien menyertakan header unik untuk tiap aksi mutasi data: Idempotency-Key: uuid-v4-abc-123.
- Server memeriksa di Redis:
- Jika key sudah pernah selesai ──► kembalikan response lama dari Redis tanpa mengeksekusi ulang ke database.
- Jika belum ──► simpan key di Redis dengan status PROCESSING, eksekusi, lalu simpan hasil.
6. Ringkasan Perbandingan
| Dimensi | Stateful App (Buruk untuk Skala) | Stateless + Redis (Standar Cloud) |
|---|---|---|
| Lokasi Session | RAM / Disk lokal server | Redis Cluster Terpusat |
| Autoscaling | Sangat sulit (harus sticky) | Bebas tambah/kurang server kapan saja |
| Server Crash | User di server itu logout | Nol dampak ke user (transparan) |
| Deploy Baru | Butuh drain panjang & resiko | Rolling update instan |
| Concurrency Control | Thread mutex lokal (hanya 1 mesin) | Distributed Lock Redis (lintas cluster) |
7. Istilah Kunci
Stateless: Desain aplikasi di mana server tidak menyimpan status user antar-request.Shared State: Lapisan penyimpanan terpusat yang diakses bersama oleh semua node worker.Redis: Data store in-memory berlatensi sangat rendah untuk session, cache, dan lock.Distributed Lock: Mekanisme penguncian resource bersama lintas banyak server independen.SETNX: Perintah Redis "Set if Not Exists" sebagai dasar mutex terdistribusi.Idempotency: Sifat operasi yang memberikan hasil identik meskipun dieksekusi berkali-kali.