Server

Cara Setting Redis Cache di VPS Ubuntu untuk Aplikasi PHP

Pertama kali saya coba pakai Redis di project PHP, hasilnya bikin kaget. Response time yang tadinya 800ms langsung turun jadi 50ms. Gila kan? Sejak itu, hampir semua project saya yang butuh performa tinggi pasti pakai Redis sebagai layer caching.

Redis itu singkatan dari Remote Dictionary Server. Secara sederhana, ini adalah in-memory data store yang super cepat karena data disimpan di RAM, bukan di disk seperti MySQL. Cocok banget buat caching query database, session management, rate limiting API, dan banyak lagi.

Kenapa Pakai Redis untuk Aplikasi PHP?

Saya pernah handle project e-commerce yang traffic-nya naik 10x pas flash sale. Tanpa caching, MySQL langsung choke. Query yang biasanya 20ms tiba-tiba jadi 2 detik karena tabel products punya 500 ribu row. Setelah pasang Redis, beban MySQL turun drastis karena data produk yang sering diakses disimpan di RAM.

Keunggulan Redis dibanding cara caching lain:

  • Kecepatan: Read/write di RAM jauh lebih cepat dari disk. Benchmark menunjukkan Redis bisa handle 100 ribu+ operasi per detik di hardware biasa
  • Data structures: Redis bukan cuma key-value biasa. Ada list, set, sorted set, hash, streams, dan geospatial indexes
  • Persistence opsional: Bisa di-set sebagai pure cache (volatile) atau persisten dengan RDB/AOF snapshots
  • Pub/Sub: Built-in messaging untuk real-time notifications
  • Atomic operations: Semua operasi Redis atomic, jadi aman untuk concurrent access

Install Redis Server di Ubuntu VPS

Proses installnya gampang banget. Saya pakai Ubuntu 24.04 LTS di contoh ini, tapi langkahnya mirip untuk versi Ubuntu lainnya.

Update dulu package list dan install Redis:


sudo apt update && sudo apt upgrade -y
sudo apt install redis-server -y

Setelah install, cek status Redis:


sudo systemctl status redis-server

Kalau outputnya active (running), berarti Redis sudah jalan. Tapi jangan senang dulu, masih ada beberapa konfigurasi penting yang perlu di-setup.

Konfigurasi Redis untuk Produksi

File konfigurasi Redis ada di /etc/redis/redis.conf. Ada beberapa setting yang wajib kamu ubah sebelum dipakai di production:

1. Bind Address

Defaultnya Redis listen di 127.0.0.1 (hanya local). Kalau aplikasi PHP kamu di server yang sama, ini sudah cukup. Tapi kalau beda server, kamu perlu bind ke IP server:


# Edit redis.conf
sudo nano /etc/redis/redis.conf

# Cari baris bind dan ubah:
bind 127.0.0.1 ::1
# Kalau perlu akses dari server lain:
# bind 127.0.0.1 ::1 192.168.1.100

2. Password Protection

Jangan pernah jalanin Redis tanpa password di production. Generate password yang kuat:


# Generate random password
openssl rand -base64 32

# Tambahkan di redis.conf
requirepass YourSuperStrongPassword123!

3. Memory Management

Ini bagian paling penting. Redis menyimpan semua data di RAM, jadi kamu harus batasi berapa banyak memory yang boleh dipakai:


# Batasi memory ke 256MB
maxmemory 256mb

# Eviction policy: hapus data yang paling jarang dipakai
maxmemory-policy allkeys-lru

Ada beberapa eviction policy yang bisa dipilih:

  • noeviction: Return error kalau memory penuh. Aman tapi bisa bikin aplikasi crash
  • allkeys-lru: Hapus key yang paling jarang diakses (Least Recently Used). Paling umum dipakai
  • volatile-lru: Hapus key yang punya TTL dan jarang diakses
  • volatile-ttl: Hapus key yang TTL-nya paling cepat expired

Setelah ubah config, restart Redis:


sudo systemctl restart redis-server

4. Tuning Kernel untuk Redis

Redis sering kasih warning tentang kernel settings. Fix dengan cara ini:


# Set vm.overcommit_memory
echo 'vm.overcommit_memory = 1' | sudo tee -a /etc/sysctl.conf

# Disable THP (Transparent Huge Pages)
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled

# Increase somaxconn
echo 'net.core.somaxconn = 65535' | sudo tee -a /etc/sysctl.conf

sudo sysctl -p

Install PHP Redis Extension

Redis server sudah jalan, sekarang kita butuh PHP extension untuk bisa konek dari kode PHP. Ada dua cara: pakai phpredis (C extension, lebih cepat) atau predis (pure PHP, lebih fleksibel).

Cara 1: phpredis (Recommended)


# Install via PECL
sudo pecl install redis

# Tambahkan ke php.ini
echo "extension=redis.so" | sudo tee /etc/php/8.3/mods-available/redis.ini
sudo phpenmod redis

# Restart PHP-FPM
sudo systemctl restart php8.3-fpm

# Verifikasi
php -m | grep redis

Cara 2: Predis (Composer)


composer require predis/predis

Di project CodeIgniter 4, saya lebih suka pakai Predis karena instalasinya gampang dan tidak butuh akses root ke server. Tapi kalau performa adalah prioritas utama, phpredis lebih cepat sekitar 20-30%.

Contoh Kode PHP dengan Redis

Sekarang bagian yang seru: menulis kode. Ini contoh basic caching pattern yang sering saya pakai:


<?php
// Koneksi ke Redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('YourSuperStrongPassword123!');

// Cek apakah data ada di cache
$cacheKey = 'products:featured';
$cachedData = $redis->get($cacheKey);

if ($cachedData) {
    // Cache hit - langsung pakai data dari Redis
    $products = json_decode($cachedData, true);
    echo "Data dari cache!";
} else {
    // Cache miss - query database
    $pdo = new PDO('mysql:host=localhost;dbname=shop', 'user', 'pass');
    $stmt = $pdo->query("SELECT * FROM products WHERE featured = 1 LIMIT 20");
    $products = $stmt->fetchAll(PDO::FETCH_ASSOC);
    
    // Simpan ke Redis, expired dalam 1 jam
    $redis->setex($cacheKey, 3600, json_encode($products));
    echo "Data dari database, disimpan ke cache!";
}

print_r($products);

Pola ini disebut Cache-Aside Pattern. Konsepnya simpel:

  1. Cek cache dulu
  2. Kalau ada (cache hit), pakai data dari cache
  3. Kalau tidak ada (cache miss), query database, simpan hasilnya ke cache
  4. Besok kalau data diminta lagi, ambil dari cache (jauh lebih cepat)

Integrasi Redis di CodeIgniter 4

Di CI4, integrasi Redis bisa dilakukan di beberapa level. Ini cara yang paling clean menurut pengalaman saya:

Setup Redis Handler untuk Session

Edit file app/Config/App.php:


<?php
// app/Config/App.php
public string $sessionDriver = 'CodeIgniter\Session\Handlers\RedisHandler';
public string $sessionSavePath = 'tcp://127.0.0.1:6379?auth=YourSuperStrongPassword123!';
public int $sessionExpiration = 7200;

Dengan ini, session user otomatis disimpan di Redis. Proses login, cart, flash messages semuanya jadi lebih cepat dibanding pakai file-based session.

Custom Cache Library

Buat library cache yang bisa dipakai di mana saja:


<?php
// app/Libraries/RedisCache.php

namespace App\Libraries;

class RedisCache
{
    private $redis;
    private $prefix = 'ci4:';
    
    public function __construct()
    {
        $this->redis = new \Redis();
        $this->redis->connect('127.0.0.1', 6379);
        $this->redis->auth('YourSuperStrongPassword123!');
    }
    
    public function get(string $key)
    {
        $data = $this->redis->get($this->prefix . $key);
        return $data ? json_decode($data, true) : null;
    }
    
    public function set(string $key, $value, int $ttl = 3600)
    {
        return $this->redis->setex(
            $this->prefix . $key,
            $ttl,
            json_encode($value)
        );
    }
    
    public function delete(string $key)
    {
        return $this->redis->del($this->prefix . $key);
    }
    
    public function flush()
    {
        // Hapus hanya key dengan prefix project kita
        $keys = $this->redis->keys($this->prefix . '*');
        if (!empty($keys)) {
            $this->redis->del($keys);
        }
    }
    
    // Cache dengan callback - praktis banget
    public function remember(string $key, int $ttl, callable $callback)
    {
        $cached = $this->get($key);
        if ($cached !== null) {
            return $cached;
        }
        
        $data = $callback();
        $this->set($key, $data, $ttl);
        return $data;
    }
}

Pakai di controller:


<?php

namespace App\Controllers;

use App\Libraries\RedisCache;

class Product extends BaseController
{
    public function index()
    {
        $cache = new RedisCache();
        
        // Satu baris untuk caching! Sangat clean
        $products = $cache->remember('products:all', 1800, function() {
            $model = new \App\Models\ProductModel();
            return $model->where('active', 1)->findAll();
        });
        
        return view('products/index', ['products' => $products]);
    }
    
    public function update($id)
    {
        // Update product...
        
        // Invalidate cache setelah update
        $cache = new RedisCache();
        $cache->delete('products:all');
        $cache->delete("products:{$id}");
        
        return redirect()->to('/products');
    }
}

Method remember() ini yang paling sering saya pakai. Cek cache, kalau tidak ada jalankan callback, simpan hasilnya. Simple dan tidak perlu tulis logic caching berulang-ulang.

Redis untuk Rate Limiting API

Kalau kamu bikin API, rate limiting itu wajib hukumnya. Redis sangat cocok untuk ini karena operasinya atomic dan cepat:


<?php

function checkRateLimit(string $ip, int $maxRequests = 60, int $windowSeconds = 60): bool
{
    $redis = new \Redis();
    $redis->connect('127.0.0.1', 6379);
    
    $key = "ratelimit:{$ip}";
    
    // Increment counter
    $current = $redis->incr($key);
    
    // Set expiry pada request pertama
    if ($current === 1) {
        $redis->expire($key, $windowSeconds);
    }
    
    // Cek apakah melebihi limit
    if ($current > $maxRequests) {
        return false; // Rate limit exceeded
    }
    
    return true; // Masih dalam limit
}

// Di middleware atau controller:
$clientIp = $this->request->getIPAddress();
if (!checkRateLimit($clientIp, 60, 60)) {
    return $this->response->setStatusCode(429)->setJSON([
        'error' => 'Too many requests. Try again in 60 seconds.'
    ]);
}

Monitoring Redis

Redis punya CLI tool yang sangat berguna untuk monitoring:


# Masuk ke Redis CLI
redis-cli -a YourSuperStrongPassword123!

# Cek info server
INFO server

# Cek memory usage
INFO memory

# Cek statistik hit/miss
INFO stats

# Monitor command secara real-time
MONITOR

# Cek semua key yang ada
KEYS *

# Cek TTL key tertentu
TTL products:featured

# Cek ukuran data
DEBUG OBJECT products:featured

Untuk monitoring yang lebih serius, kamu bisa pakai redis-exporter dengan Prometheus + Grafana. Tapi untuk awal, redis-cli INFO sudah cukup.

Common Pitfalls dan Cara Menghindarinya

Saya sudah cukup lama pakai Redis, dan ini masalah yang paling sering saya temui:

1. Cache Stampede (Thundering Herd)

Kalau cache expired dan 1000 request datang barengan, semuanya langsung ke database. Solusinya pakai locking:


<?php
public function getWithLock(string $key, int $ttl, callable $callback)
{
    $data = $this->get($key);
    if ($data !== null) {
        return $data;
    }
    
    $lockKey = $key . ':lock';
    
    // Coba ambil lock (setnx = set if not exists)
    if ($this->redis->setnx($lockKey, 1)) {
        $this->redis->expire($lockKey, 10); // Lock expired 10 detik
        
        try {
            $data = $callback();
            $this->set($key, $data, $ttl);
            return $data;
        } finally {
            $this->redis->del($lockKey);
        }
    }
    
    // Kalau tidak dapat lock, tunggu dan retry
    usleep(100000); // 100ms
    return $this->getWithLock($key, $ttl, $callback);
}

2. Lupa Invalidate Cache

Ini masalah klasik. Data di database sudah diubah, tapi cache masih data lama. Solusi: selalu invalidate cache setelah write operation. Buat helper method dan konsisten pakai di mana-mana.

3. Key Naming yang Berantakan

Pakai konvensi penamaan yang konsisten:


# Format: {module}:{entity}:{id}:{attribute}
products:detail:123
products:list:featured
users:session:abc123
api:ratelimit:192.168.1.1

4. Tidak Set TTL

Setiap key harus punya TTL. Kalau tidak, cache akan terus menumpuk sampai RAM habis. Default TTL yang biasa saya pakai:

  • Data yang sering berubah: 5-15 menit
  • Data yang jarang berubah: 1-6 jam
  • Static data: 24 jam
  • Session: 2 jam

Benchmark: Dengan vs Tanpa Redis

Ini hasil benchmark sederhana yang saya buat di VPS 2GB RAM dengan 50.000 row di tabel products:

  • Tanpa Redis: Rata-rata 450ms per request, 220 requests/detik
  • Dengan Redis: Rata-rata 12ms per request, 8.500 requests/detik

Peningkatan performa hampir 38x lipat. Dan ini cuma untuk satu tabel. Kalau aplikasinya punya banyak tabel yang sering di-query, efeknya makin terasa.

Kesimpulan

Redis itu game changer untuk aplikasi PHP yang butuh performa tinggi. Installasi dan konfigurasinya relatif mudah, tapi dampaknya luar biasa besar. Mulai dari caching query database sampai session management, Redis bisa handle semuanya dengan cepat dan efisien.

Kalau kamu baru mulai, saran saya: pasang Redis di project yang paling bermasalah dengan performa dulu. Rasakan sendiri bedanya. Setelah itu, saya yakin kamu akan ketagihan dan mulai pakai Redis di semua project.

Satu hal yang perlu diingat: Redis itu bukan pengganti database. Ini adalah layer tambahan untuk mempercepat akses data. Tetap optimasi query database kamu, tambah index yang tepat, dan pakai Redis sebagai pelengkap, bukan solusi utama.


You may also like


0 Comments


Leave a Reply

Comments with links or spam keywords will be rejected.
Scroll to Top