Tutorial

Redis Cache: Cara Meningkatkan Performa Website 10x Lipat

Redis Cache: Cara Meningkatkan Performa Website 10x Lipat
Redis (Remote Dictionary Server) adalah in-memory data store yang bisa digunakan sebagai caching layer, message broker, atau database primer. Dengan response time dalam mikrodetik, Redis bisa meningkatkan performa website secara dramatis — dari response time beberapa detik menjadi di bawah 10ms. ## Mengapa Redis? **In-Memory Speed.** Redis menyimpan data di RAM, bukan disk. Akses data dari RAM sekitar 100.000x lebih cepat dari disk SSD. Ini artinya cache lookup yang biasanya memakan waktu 50-200ms bisa selesai dalam <1ms. **Lebih dari Sekedar Caching.** Redis mendukung berbagai data structures: strings, hashes, lists, sets, sorted sets, dan hyperloglogs. Ini membuatnya versatile untuk berbagai use case. **Built-in Persistence.** Berbeda dari Memcached, Redis bisa persist data ke disk sehingga tidak hilang saat server restart. **Pub/Sub dan Streams.** Redis bisa digunakan sebagai message broker untuk microservices atau real-time notifications. ## Install Redis ### Ubuntu/Debian ```bash apt update && apt install -y redis-server systemctl enable redis-server systemctl start redis-server ``` ### Docker ```bash docker run -d --name redis \ -p 6379:6379 \ -v redis-data:/data \ --restart unless-stopped \ redis:7-alpine redis-server --appendonly yes ``` ### Verifikasi ```bash redis-cli ping # PONG ``` ## Konfigurasi Dasar Edit `/etc/redis/redis.conf`: ### Memory Limit ``` maxmemory 256mb maxmemory-policy allkeys-lru ``` **allkeys-lru** artinya Redis akan menghapus key yang paling jarang digunakan ketika memory penuh. Policy lain: - `volatile-lru`: Hanya hapus key yang punya expiry time - `allkeys-random`: Hapus key random - `noeviction`: Jangan hapus apapun, return error jika memory penuh ### Security ``` requirepass your-strong-password-here bind 127.0.0.1 ::1 ``` **Penting:** Redis default tidak punya password. Jika Redis exposed ke internet tanpa password, itu celah keamanan kritis. ### Persistence (Opsional) ``` # RDB snapshots save 900 1 save 300 10 save 60 10000 # AOF (Append Only File) appendonly yes appendfsync everysec ``` ## Use Cases untuk Website ### 1. Page Cache Simpan HTML output yang sudah di-render di Redis. request berikutnya langsung ambil dari Redis tanpa proses PHP/Python/Node. **PHP dengan Redis:** ```php connect('127.0.0.1', 6379); $redis->auth('password'); $cacheKey = 'page_' . md5($_SERVER['REQUEST_URI']); $cached = $redis->get($cacheKey); if ($cached) { echo $cached; exit; } ob_start(); // render page... $html = ob_get_contents(); ob_end_clean(); $redis->setex($cacheKey, 3600, $html); // cache 1 jam echo $html; ``` ### 2. Session Store Alih-alih simpan session di file (lambat untuk multi-server), simpan di Redis: **PHP Session Handler:** ```ini ; php.ini session.save_handler = redis session.save_path = "tcp://127.0.0.1:6379?auth=password" ``` **Express.js (Node):** ```javascript const session = require('express-session'); const RedisStore = require('connect-redis').default; const { createClient } = require('redis'); const redisClient = createClient({ url: 'redis://:password@localhost:6379' }); redisClient.connect(); app.use(session({ store: new RedisStore({ client: redisClient }), secret: 'your-secret', resave: false, saveUninitialized: false, })); ``` ### 3. Database Query Cache Cache hasil query database yang sering diakses: ```python import redis import json r = redis.Redis(host='localhost', port=6379, password='password', decode_responses=True) def get_popular_posts(): cache_key = 'popular_posts' cached = r.get(cache_key) if cached: return json.loads(cached) # Query database posts = db.query("SELECT * FROM posts ORDER BY views DESC LIMIT 10") # Cache selama 5 menit r.setex(cache_key, 300, json.dumps(posts)) return posts ``` ### 4. Rate Limiting Batasi jumlah request dari IP tertentu: ```python def is_rate_limited(ip, limit=100, window=60): key = f"rate:{ip}" current = r.incr(key) if current == 1: r.expire(key, window) return current > limit ``` ### 5. Real-time Counter Hitung views, likes, atau activity secara real-time: ```python # Increment view count r.incr(f"post:{post_id}:views") # Get trending posts (sorted set) r.zincrby("trending", 1, post_id) # Get top 10 trending trending = r.zrevrange("trending", 0, 9, withscores=True) ``` ## Monitoring Redis ### Redis Info ```bash redis-cli info memory redis-cli info stats redis-cli info clients ``` ### Key Metrics - **used_memory:** RAM yang digunakan - **connected_clients:** Jumlah koneksi aktif - **ops_per_sec:** Operasi per detik - **hit_rate:** Cache hit ratio (target: >95%) ```bash # Hit rate calculation redis-cli info stats | grep -E "(keyspace_hits|keyspace_misses)" ``` ### Redis Commander (Web UI) ```bash docker run -d --name redis-commander \ -p 8081:8081 \ -e REDIS_HOSTS=local:redis:6379 \ rediscommander/redis-commander ``` ## Best Practices **Gunakan Expiry Time.** Selalu set TTL pada cache keys untuk mencegah memory leak: ``` redis.setex("key", 3600, "value") # 1 jam ``` **Cache Invalidation.** Strategy untuk invalidate cache saat data berubah: - **TTL-based:** Set expiry time dan biarkan expired - **Event-based:** Invalidate cache saat data di-update - **Version-based:** Sertakan version number di cache key **Connection Pool.** Jangan buka-buka koneksi Redis. Gunakan connection pool: ```python pool = redis.ConnectionPool(host='localhost', port=6379, max_connections=20) r = redis.Redis(connection_pool=pool) ``` **Jangan Simpan Semua di Redis.** Redis ada di RAM. Simpan hanya data yang benar-benar sering diakses. Data archival sebaiknya di database disk. Redis bukan sekedar tool caching — ini adalah Swiss Army Knife untuk performa dan real-time data. Dengan implementasi yang benar, Redis bisa menjadi game-changer untuk website kamu.