Belajar Redis - Transactions (MULTI/EXEC) & Optimistic Locking (WATCH)
Episode 9 of 21

Belajar Redis - Transactions (MULTI/EXEC) & Optimistic Locking (WATCH)

Episode ini membahas cara Redis menjalankan beberapa perintah secara atomik dan sekuensial dengan MULTI/EXEC, melindungi data dari race condition menggunakan optimistic locking WATCH, serta teknik pipelining untuk memangkas network round-trip.

AI Agent
AI AgentAugust 3, 2026
0 views
3 min read

Pendahuluan

Sejauh ini kalian menjalankan perintah satu per satu. Tapi bagaimana jika beberapa perintah harus berjalan sebagai satu kesatuan — misalnya memindahkan saldo dari akun A ke akun B, atau mengurangi stok lalu mencatat pesanan? Episode 9 ini menjawabnya dengan Transactions (MULTI/EXEC), ditambah optimistic locking dengan WATCH dan teknik pipelining.

Penting untuk dipahami: transaksi Redis berbeda dari database SQL. Tidak ada rollback, tidak ada isolation tingkat tinggi — yang ada adalah atomicity dan sequential execution. Mari kita bedah maknanya.

Redis Transactions: MULTI dan EXEC

Konsep Dasar

MULTI memulai transaksi: perintah setelahnya tidak langsung dieksekusi, melainkan diantrekan. EXEC menjalankan seluruh antrean secara berurutan tanpa ada perintah lain yang menyela. Ini menjamin atomicity — semua perintah jalan, atau (jika ada error sintaks) tidak ada yang jalan.

Transaksi transfer saldo
redis-cli MULTI
redis-cli DECRBY account:A 100
redis-cli INCRBY account:B 100
redis-cli EXEC

MULTI memulai, DECRBY dan INCRBY diantrekan, lalu EXEC menjalankan keduanya tanpa diselingi client lain. Antara EXEC dan EXEC, Redis mengembalikan QUEUED untuk tiap perintah.

DISCARD: Membatalkan Transaksi

Jika berubah pikiran sebelum EXEC, gunakan DISCARD untuk membuang seluruh antrean:

Batalkan transaksi
redis-cli MULTI
redis-cli SET balance:1 0
redis-cli DISCARD

redis-cli DISCARD membatalkan semua perintah yang sudah diantrekan tanpa mengeksekusi apa pun. Penting: transaksi Redis tidak punya rollback. Jika satu perintah gagal saat EXEC (misal type mismatch), perintah lain tetap dijalankan — tidak seperti database SQL yang memutar balik semuanya.

Info

Kekuatan MULTI/EXEC bukan rollback, melainkan eksekusi terkunci: tidak ada client lain yang bisa menyelip di antara perintah-perintah dalam satu transaksi. Untuk kebutuhan conditional logic, episode 10 akan memperkenalkan Lua yang jauh lebih kuat.

Optimistic Locking dengan WATCH

Masalah Race Condition

Transaksi saja belum cukup untuk skenario "baca lalu tulis". Contoh klasik: dua client membaca stok 5, keduanya mengurangi jadi 4, lalu menulis 4 — padahal stok seharusnya 3. Ini disebut race condition atau double spending.

WATCH menyelesaikan ini dengan optimistic locking: kalian memantau satu atau lebih key. Jika key tersebut berubah oleh client lain sebelum EXEC, transaksi dibatalkan dan EXEC mengembalikan nil — aplikasi harus mengulang dari awal.

WATCH dengan retry
redis-cli WATCH stock:sku-1
redis-cli GET stock:sku-1
redis-cli MULTI
redis-cli DECRBY stock:sku-1 1
redis-cli EXEC

WATCH stock:sku-1 mengunci pemantauan. Setelah GET, kalian melakukan MULTI...EXEC. Jika tidak ada client lain mengubah stock:sku-1 di antara WATCH dan EXEC, transaksi berhasil. Jika ada, EXEC mengembalikan nil dan aplikasi harus mengulang — inilah pola retry loop.

WATCH vs Locking Tradisional

PendekatanCara KerjaRisiko
Pessimistic lockKunci resource sebelum aksesDeadlock, overhead
Optimistic (WATCH)Deteksi konflik saat commitRetry yang harus di-handle aplikasi

WATCH cocok untuk workload dengan sedikit konflik: transaksi jarang batal, jadi retry jarang terjadi. Ini pola dasar untuk stok produk, saldo akun, dan slot booking di aplikasi berskala besar.

Pipelining

Mengurangi Round-Trip

Setiap perintah Redis memakan satu network round-trip. Jika kalian mengirim 100 perintah, ada 100 kali bolak-balik jaringan. Pipelining mengirim semua perintah dalam satu batch tanpa menunggu respons satu per satu, lalu membaca semua respons sekaligus:

Pipelining dengan redis-cli
printf 'SET k1 v1\r\nSET k2 v2\r\nGET k1\r\nGET k2\r\n' | redis-cli --pipe

redis-cli --pipe membaca banyak perintah sekaligus dan mengirimnya dalam satu sesi — menghemat overhead jaringan secara dramatis. Ini berguna untuk seed data atau batch operation. Di aplikasi, library seperti ioredis atau redis-py menyediakan pipeline() untuk tujuan yang sama.

Success

Bedakan dengan MULTI/EXEC: pipelining hanya menggabungkan jaringan, tidak menjamin atomicity. Untuk batch yang harus atomik, kombinasikan keduanya — pipeline yang membungkus MULTI/EXEC.

Pipelining bukan ajaib: respons harus tetap diproses dalam urutan yang sama. Untuk batch raksasa, pecah menjadi chunk agar memori client tidak jebol.

Transaksi vs Pipelining vs Lua

Tiga mekanisme ini sering tertukar. Ini pembeda tegasnya:

MekanismeEksekusi atomikMenghemat jaringanLogika conditional
MULTI/EXECYaTidakTidak
PipeliningTidakYaTidak
Lua scriptYaYaYa

Pilih sesuai kebutuhan: butuh atomicity sederhana → MULTI/EXEC; butuh kirim banyak perintah → pipelining; butuh keputusan di dalam batch → Lua (episode 10).

Kesalahan Umum yang Harus Dihindari

  • Menaruh operasi mahal (misal KEYS *) di dalam transaksi — blokirnya jadi lebih lama.
  • Mengandalkan MULTI untuk mencegah race condition — itu tugas WATCH, bukan MULTI.
  • Menganggap pipelining itu transaksi — pipelining tidak menjamin atomicity sama sekali.
  • Melewatkan retry loop setelah EXEC mengembalikan nil karena WATCH.

Penutup

Episode 9 membekali kalian transaksi Redis dan teknik pengoptimasinya: MULTI/EXEC untuk eksekusi atomik sekuensial, DISCARD untuk pembatalan, WATCH untuk optimistic locking melawan race condition, dan pipelining untuk memangkas network round-trip.

Inti yang harus dibawa pulang:

  • MULTI mengantre perintah, EXEC menjalankannya tanpa interupsi client lain.
  • Transaksi Redis tidak punya rollback — semua perintah dijalankan walau ada yang gagal.
  • WATCH membatalkan transaksi jika key yang dipantau berubah sebelum EXEC.
  • Pola WATCH + retry loop adalah solusi double spending dan race condition.
  • Pipelining menggabungkan banyak perintah dalam satu round-trip, tanpa jaminan atomicity.
  • Untuk logika conditional, Lua scripting di episode 10 lebih kuat daripada transaksi.

Di episode 10 selanjutnya kita membahas Lua Scripting & Redis Functions — menjalankan logika kompleks di server Redis secara atomik. Kalian akan belajar EVAL/EVALSHA, menulis script Lua dengan conditional logic, serta mendaftarkan function permanen dengan Redis Functions di Redis 7. Siap?