Redis sering diperkenalkan sebagai database yang sangat cepat. Deskripsi itu benar, tetapi terlalu pendek untuk membantu saat aplikasi mulai menerima traffic nyata. Pertanyaan yang lebih penting adalah: data apa yang layak ditempatkan di Redis, apa konsekuensinya saat Redis restart, dan kapan Redis sebaiknya tidak dipakai?

Redis adalah in-memory data store dengan struktur data native seperti string, hash, list, set, sorted set, stream, dan bitmap. Data utama berada di RAM, sehingga operasi sederhana bisa sangat cepat. Redis juga mendukung persistence ke disk, replication, Pub/Sub, Streams, dan mode cluster. Fitur-fitur ini membuat Redis berguna untuk lebih dari sekadar cache, tetapi tidak otomatis menjadikannya pengganti PostgreSQL atau database transaksional lain.

Redis paling cocok untuk apa

Gunakan Redis ketika data memiliki salah satu karakteristik berikut:

  • Bisa dibuat ulang dari sumber utama, seperti cache hasil query atau response API.
  • Memerlukan latency rendah dan akses berdasarkan key.
  • Memiliki masa berlaku jelas, misalnya session, OTP, rate-limit counter, atau lock sementara.
  • Perlu operasi atomik sederhana, seperti increment counter dan queue ringan.
  • Perlu koordinasi antar proses melalui Pub/Sub atau Streams.

Jangan menjadikan Redis satu-satunya tempat untuk data yang tidak boleh hilang tanpa memahami persistence, replication, failover, dan prosedur restore. Untuk order, saldo, invoice, dan data relasional utama, database transaksional biasanya tetap menjadi source of truth.

Menjalankan Redis secara lokal

Cara tercepat untuk mencoba Redis adalah Docker:

docker run -d --name redis-dev -p 6379:6379 redis:7-alpine
redis-cli -h 127.0.0.1 ping
# PONG

Untuk project yang memakai Docker Compose:

services:
  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 10

volumes:
  redis-data:

Volume penting karena container yang dihapus tidak seharusnya menghapus data persistence secara tidak sengaja. Pada environment production, jangan expose port 6379 ke internet. Redis sebaiknya berada di private network dan dilindungi password atau ACL.

Operasi dasar dengan redis-cli

Redis menyimpan nilai dengan key. Contoh paling dasar:

redis-cli
SET user:42:name "Afry"
GET user:42:name
EXPIRE user:42:name 3600
TTL user:42:name
DEL user:42:name

EXPIRE mengubah key menjadi data sementara. TTL bukan sekadar fitur kenyamanan; ia mencegah cache, token, dan counter memenuhi RAM tanpa batas. Untuk melihat penggunaan RAM secara kasar:

INFO memory
MEMORY USAGE user:42:name

Hindari KEYS * di instance production besar karena dapat memblokir event loop saat jumlah key sangat banyak. Gunakan SCAN:

SCAN 0 MATCH session:* COUNT 100

Struktur data yang perlu dipahami

String: cache dan counter

String cocok untuk response JSON, feature flag kecil, token sementara, dan counter.

SET cache:article:redis '{"title":"Redis"}' EX 300
INCR rate:user:42
EXPIRE rate:user:42 60

INCR bersifat atomik. Itu membuatnya berguna untuk rate limit sederhana tanpa read-modify-write race condition.

Hash: objek kecil

Hash menyimpan beberapa field di bawah satu key:

HSET user:42 name "Afry" role "admin" plan "pro"
HGET user:42 role
HGETALL user:42

Hash cocok untuk session atau metadata kecil. Jangan memasukkan objek berukuran sangat besar tanpa mengukur memory fragmentation dan pola update-nya.

Set: membership unik

Set berguna untuk daftar unik, misalnya user yang sudah menerima notifikasi:

SADD notification:article:100 sent:user:42 sent:user:77
SISMEMBER notification:article:100 sent:user:42
SCARD notification:article:100

Sorted set: ranking dan time window

Sorted set menyimpan member dengan score. Ini cocok untuk leaderboard, jadwal, dan rate limit berbasis timestamp:

ZADD leaderboard 1200 user:42
ZREVRANGE leaderboard 0 9 WITHSCORES

List dan Streams: queue dengan kebutuhan berbeda

List sering dipakai untuk queue sederhana memakai LPUSH dan BRPOP. Redis Streams lebih tepat ketika kamu memerlukan consumer group, acknowledgement, dan pembacaan berdasarkan ID:

XADD jobs * type email recipient user@example.com
XGROUP CREATE jobs workers $ MKSTREAM
XREADGROUP GROUP workers worker-1 COUNT 10 BLOCK 5000 STREAMS jobs >
XACK jobs workers 1710000000000-0

Streams bukan pengganti message broker untuk semua skenario. Evaluasi retention, retry, dead-letter handling, observability, dan kebutuhan ordering sebelum menggunakannya sebagai event backbone.

Redis sebagai cache yang benar

Pola cache-aside biasanya paling mudah dirawat:

  1. Aplikasi membaca key Redis.
  2. Jika ada, aplikasi mengembalikan cached value.
  3. Jika tidak ada, aplikasi membaca database utama.
  4. Aplikasi menyimpan hasil ke Redis dengan TTL.
  5. Response dikembalikan ke client.

Contoh Python:

import json
import redis

r = redis.Redis(host="redis", port=6379, decode_responses=True)

def get_article(article_id, db):
    key = f"article:{article_id}"
    cached = r.get(key)
    if cached:
        return json.loads(cached)

    article = db.fetch_article(article_id)
    if article is not None:
        r.set(key, json.dumps(article), ex=300)
    return article

Masalah paling umum adalah stale data. Saat artikel diubah, hapus atau update key cache terkait. TTL membantu membatasi umur data, tetapi TTL bukan strategi invalidasi yang lengkap. Untuk object dengan banyak relasi, versioned key atau event invalidation sering lebih mudah diprediksi.

Session, rate limiting, dan distributed lock

Redis cocok untuk session karena aplikasi bisa membaca session dari beberapa replica tanpa sticky session. Simpan identifier yang tidak sensitif, TTL session, dan hindari menaruh password atau secret mentah.

Rate limiting sederhana dapat memakai counter dengan window tetap:

key = f"rate:{user_id}:{minute}"
count = r.incr(key)
if count == 1:
    r.expire(key, 60)
if count > 100:
    raise TooManyRequests()

Untuk kebutuhan rate limit yang lebih presisi, gunakan Lua script atau algoritma sliding window. Lock Redis memerlukan perhatian pada TTL, ownership token, dan release yang aman. SET lock:key token NX EX 30 lebih aman daripada SETNX lalu EXPIRE terpisah karena dua operasi itu bisa terputus di tengah.

Persistence dan durability

Redis memiliki dua bentuk persistence utama:

Mode Cara kerja Trade-off
RDB Snapshot berkala File ringkas, tetapi perubahan sejak snapshot terakhir bisa hilang
AOF Mencatat operasi write Recovery lebih granular, file dan overhead write bisa lebih besar

Untuk cache, kehilangan seluruh data mungkin dapat diterima. Untuk queue atau session penting, keputusan persistence harus mengikuti RPO dan RTO, bukan asumsi bahwa Redis selalu aman atau selalu tidak aman.

Persistence juga bukan backup. Salinannya harus diuji restore, disimpan di lokasi berbeda, dan dilindungi dari penghapusan yang sama dengan instance utama. Replication meningkatkan availability dan read scaling, tetapi replica bukan backup karena kesalahan atau penghapusan dapat ikut direplikasi.

Security dan operasi production

Checklist minimum:

  • Bind Redis ke private interface, bukan 0.0.0.0 tanpa alasan.
  • Gunakan ACL Redis untuk membatasi command dan key pattern per aplikasi.
  • Enkripsi traffic jika Redis melewati network yang tidak sepenuhnya dipercaya.
  • Jangan menaruh secret di command line atau commit file konfigurasi.
  • Batasi memory dengan maxmemory dan pilih eviction policy sesuai workload.
  • Pantau used_memory, hit rate, evicted keys, blocked clients, latency, dan replication lag.
  • Atur client timeout, connection pool, dan retry dengan backoff.
  • Hindari retry tanpa batas karena dapat memperparah overload saat Redis lambat.

maxmemory-policy allkeys-lru umum untuk cache, sedangkan queue dan data yang tidak boleh hilang memerlukan kebijakan yang berbeda. Jangan memilih eviction policy sebelum tahu mana key yang boleh dibuang.

High availability: Sentinel atau Cluster

Redis Sentinel memantau primary, membantu failover, dan cocok untuk topology primary-replica yang tidak memerlukan sharding. Redis Cluster membagi key ke beberapa slot dan dipakai ketika satu node tidak cukup menampung memory atau throughput.

Cluster menambah kompleksitas: client harus mendukung redirect, multi-key operation memiliki batasan slot, dan migrasi slot perlu direncanakan. Sentinel bukan sharding. Sebaliknya, Cluster bukan otomatis menyelesaikan backup, observability, atau desain data yang buruk.

Untuk tim kecil, managed Redis sering lebih masuk akal daripada mengoperasikan Sentinel atau Cluster sendiri. Biayanya lebih tinggi, tetapi mengurangi beban patching, failover, monitoring, dan recovery. Self-hosted masuk akal jika kamu memang membutuhkan kontrol biaya, lokasi data, atau konfigurasi khusus.

Pola yang sering gagal

  • Menaruh database utama hanya di Redis karena latency-nya rendah.
  • Tidak memberi TTL pada key sementara.
  • Menggunakan KEYS * saat debugging di jam sibuk.
  • Menganggap replica sama dengan backup.
  • Menggunakan Redis Pub/Sub untuk event yang wajib tidak hilang; subscriber yang offline dapat melewatkan pesan.
  • Menggunakan satu Redis untuk cache, queue, lock, dan session tanpa memory budget atau isolation.
  • Menyalakan retry agresif ketika Redis down sehingga semua aplikasi melakukan reconnect storm.

Cara memilih desain

Pilih cache-aside jika data dapat dibuat ulang dan stale beberapa detik masih dapat diterima. Pilih session store jika aplikasi berjalan di banyak instance dan session perlu konsisten. Pilih Streams jika perlu consumer group dan acknowledgement. Pilih database utama jika data membutuhkan transaksi, query relasional, constraint, dan durability kuat.

Mulai dari satu instance private dengan metrics yang jelas untuk workload kecil. Tambahkan persistence, replica, Sentinel, atau Cluster hanya ketika RPO, RTO, kapasitas, atau availability memang membutuhkannya. Setiap lapisan tambahan memiliki biaya operasi yang harus dibayar.

Checklist implementasi

  • [ ] Redis tidak terbuka langsung ke internet.
  • [ ] Semua key cache dan token memiliki TTL.
  • [ ] Source of truth tetap jelas.
  • [ ] Memory limit dan eviction policy sudah dipilih berdasarkan workload.
  • [ ] Persistence dan backup punya RPO/RTO tertulis.
  • [ ] Restore pernah diuji, bukan hanya backup yang dibuat.
  • [ ] Metrics latency, memory, evictions, hit rate, dan connections dipantau.
  • [ ] Client memakai connection pool dan retry backoff.
  • [ ] Prefix key mencegah benturan antar aplikasi.
  • [ ] Ada prosedur ketika Redis unavailable.

Kesimpulan praktis

Redis paling kuat ketika dipakai untuk data cepat, sementara, dan terukur: cache, session, counter, lock, queue ringan, dan koordinasi antar proses. Ia bukan jawaban universal untuk persistence dan transaksi.

Mulailah dari kebutuhan data, TTL, failure mode, dan recovery target. Setelah itu pilih struktur data dan topology Redis yang paling sederhana yang masih memenuhi kebutuhan. Kesederhanaan di sini bukan berarti fitur paling sedikit, tetapi jumlah komponen yang bisa kamu operasikan dan pulihkan dengan percaya diri.