Kembali ke Blog
Tutorial#redis#caching#performa#backend#database

Redis Caching: Strategi Buat Aplikasi 10x Lebih Cepat

Database query yang lambat adalah pembunuh performa nomor satu. Dengan Redis caching yang benar, response time bisa turun dari detik ke milidetik. Ini strategi dan implementasinya.

Muhamad Putra Aulia Hidayat

Muhamad Putra Aulia Hidayat

28 Maret 20263 menit baca

Redis Caching: Dari Lambat ke Kilat

Anda punya web app yang makin lambat seiring bertambahnya data? Sebelum upgrade server, coba dulu implementasi caching yang benar. Pengalaman kami: caching yang proper bisa kurangi load database 80-90%.

Kapan Harus Pakai Caching?

  • Data yang sering dibaca tapi jarang berubah (produk, kategori, config)
  • Hasil kalkulasi yang mahal (laporan, aggregasi)
  • Session user dan auth token
  • Rate limiting counter
  • Leaderboard dan ranking

Strategi Caching

Cache-Aside (Paling Umum)

import redis
import json
from typing import Optional

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

async def get_product(product_id: str) -> dict:
    cache_key = f"product:{product_id}"
    
    # 1. Cek cache dulu
    cached = r.get(cache_key)
    if cached:
        return json.loads(cached)  # Cache hit!
    
    # 2. Cache miss - ambil dari database
    product = await db.query(f"SELECT * FROM products WHERE id = $1", product_id)
    
    # 3. Simpan ke cache dengan TTL 1 jam
    r.setex(cache_key, 3600, json.dumps(product))
    
    return product

def invalidate_product(product_id: str):
    r.delete(f"product:{product_id}")

Write-Through Cache

async def update_product(product_id: str, data: dict) -> dict:
    # Update database
    updated = await db.execute(
        "UPDATE products SET name=$1, price=$2 WHERE id=$3 RETURNING *",
        data["name"], data["price"], product_id
    )
    
    # Langsung update cache juga
    cache_key = f"product:{product_id}"
    r.setex(cache_key, 3600, json.dumps(updated))
    
    return updated

Cache Stampede Prevention

Masalah: ketika cache expired, ribuan request serentak hit database.

import asyncio

_locks: dict = {}

async def get_with_lock(key: str, fetch_fn, ttl: int = 3600):
    cached = r.get(key)
    if cached:
        return json.loads(cached)
    
    # Gunakan lock untuk prevent stampede
    if key not in _locks:
        _locks[key] = asyncio.Lock()
    
    async with _locks[key]:
        # Double-check setelah dapat lock
        cached = r.get(key)
        if cached:
            return json.loads(cached)
        
        data = await fetch_fn()
        r.setex(key, ttl, json.dumps(data))
        return data

Caching di Next.js dengan Upstash Redis

import { Redis } from "@upstash/redis"

const redis = Redis.fromEnv()

export async function getCachedProducts() {
  const cached = await redis.get<Product[]>("products:all")
  if (cached) return cached
  
  const products = await db.select().from(productsTable)
  
  // Cache selama 5 menit
  await redis.setex("products:all", 300, products)
  
  return products
}

// Invalidate saat ada perubahan
export async function createProduct(data: NewProduct) {
  const product = await db.insert(productsTable).values(data).returning()
  await redis.del("products:all") // Hapus cache
  return product
}

Pattern Caching Lanjutan

Sliding Window Rate Limiter

def is_rate_limited(user_id: str, limit: int = 100, window: int = 60) -> bool:
    key = f"ratelimit:{user_id}"
    pipe = r.pipeline()
    pipe.incr(key)
    pipe.expire(key, window)
    result = pipe.execute()
    
    current_count = result[0]
    return current_count > limit

Cache Tags untuk Invalidasi Group

def cache_with_tags(key: str, data: any, tags: list[str], ttl: int = 3600):
    # Simpan data
    r.setex(key, ttl, json.dumps(data))
    
    # Daftarkan key ke setiap tag
    for tag in tags:
        r.sadd(f"tag:{tag}", key)
        r.expire(f"tag:{tag}", ttl + 60)

def invalidate_tag(tag: str):
    keys = r.smembers(f"tag:{tag}")
    if keys:
        r.delete(*keys)
    r.delete(f"tag:{tag}")

# Pakai:
cache_with_tags("product:123", product_data, tags=["products", "category:elektronik"])

# Invalidate semua product sekaligus
invalidate_tag("products")

Monitoring Cache

# Cek hit ratio
redis-cli info stats | grep keyspace

# Monitor perintah real-time
redis-cli monitor

# Cek memory usage
redis-cli info memory

Target hit ratio yang baik adalah >80%. Kalau di bawah itu, perlu review strategi TTL dan key design.

Butuh implementasi caching untuk aplikasi Anda yang mulai lambat? Konsultasi dengan kami — kami bisa audit dan optimasi performa aplikasi Anda.

rediscachingperformabackenddatabase

Newsletter Digital Uptime

Tips teknologi & bisnis mingguan

Bergabung dengan 2,500+ subscriber yang mendapatkan insight teknologi, tutorial development, dan tips bisnis digital langsung ke inbox mereka setiap minggu.

Tidak ada spam. Unsubscribe kapan saja.

Artikel Terkait

Kami menggunakan cookies untuk meningkatkan pengalaman Anda di website ini. Dengan melanjutkan, Anda menyetujui penggunaan cookies sesuai Kebijakan Privasi kami.