Redis sebagai cache layer di Laravel bekerja dengan pola sederhana: sebelum menjalankan query atau perhitungan mahal, aplikasi mengecek Redis; kalau datanya ada, langsung dipakai, kalau tidak, dihitung lalu disimpan untuk permintaan berikutnya. Dengan Cache::remember(), pola ini cukup satu baris. Tantangan sebenarnya ada di menentukan apa yang di-cache, berapa lama, dan kapan cache dihapus saat data berubah.
Setup Redis di Laravel
# .env
CACHE_STORE=redis
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
Ekstensi PHP phpredis lebih cepat. Kalau tidak bisa dipasang, gunakan paket predis/predis dan set REDIS_CLIENT=predis. Di environment Docker, host Redis adalah nama service, seperti dijelaskan di Docker untuk Laravel.
Cek koneksi:
php artisan tinker --execute 'Cache::put("tes", "ok", 60); echo Cache::get("tes");'
Pola Dasar: Cache-Aside dengan Redis
$categories = Cache::remember('categories:menu', now()->addHour(), function () {
return Category::query()
->withCount('posts')
->orderBy('sort_order')
->get(['id', 'name', 'slug']);
});
- Kunci yang jelas: pakai pola
entitas:keterangan:id, misalnyaproduct:detail:42. - TTL masuk akal: data yang jarang berubah (menu, pengaturan) bisa berjam-jam; data yang sering berubah (stok) cukup hitungan detik atau tanpa cache.
- Simpan data sederhana: array atau koleksi kecil lebih aman daripada model dengan banyak relasi yang ikut terserialisasi.
Invalidasi: Hapus Cache Saat Data Berubah
Data basi biasanya terjadi karena cache tidak dihapus saat data diubah. Hubungkan penghapusan cache ke event model:
class Category extends Model
{
protected static function booted(): void
{
static::saved(fn () => Cache::forget('categories:menu'));
static::deleted(fn () => Cache::forget('categories:menu'));
}
}
Untuk data per entitas:
// baca
$product = Cache::remember("product:detail:{$id}", now()->addMinutes(30),
fn () => Product::with('images')->findOrFail($id)->toArray());
// saat produk diperbarui
Cache::forget("product:detail:{$product->id}");
Cache tags untuk menghapus banyak kunci sekaligus
Cache::tags(['products'])->remember("product:list:page:{$page}", 600, fn () => ...);
// hapus semua daftar produk saat ada perubahan
Cache::tags(['products'])->flush();
Tags hanya didukung driver tertentu seperti Redis dan Memcached, tidak untuk driver file atau database.
Mencegah Cache Stampede
Saat cache populer kedaluwarsa, ratusan request bisa menjalankan query mahal yang sama secara bersamaan. Dua cara mengatasinya:
Lock
$report = Cache::get('report:daily');
if ($report === null) {
$report = Cache::lock('report:daily:lock', 30)->block(10, function () {
return Cache::remember('report:daily', now()->addHour(), fn () => DailyReport::build());
});
}
Flexible cache (stale-while-revalidate)
$stats = Cache::flexible('dashboard:stats', [300, 900], fn () => Stats::compute());
Dengan Cache::flexible(), data dianggap segar selama 5 menit. Antara menit 5 sampai 15, pengguna tetap mendapat data lama sementara nilai baru dihitung di belakang layar. Setelah 15 menit, data dihitung ulang seperti biasa.
Apa yang Layak Di-cache
| Layak | Hati-hati | Jangan |
|---|---|---|
| Menu, kategori, pengaturan situs | Daftar produk dengan filter (banyak kombinasi kunci) | Saldo, stok saat checkout |
| Hasil agregasi laporan | Data per pengguna (jumlah kunci membengkak) | Data yang wajib selalu real-time |
| Respons API pihak ketiga | Halaman dengan konten pribadi | Token atau rahasia tanpa enkripsi |
Redis untuk Queue dan Session
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
Redis cocok untuk queue karena cepat dan mendukung Laravel Horizon untuk memantau job. Kalau cache, queue, dan session memakai satu server Redis, pisahkan database atau koneksinya di config/database.php. Dengan begitu Cache::flush() tidak ikut menghapus antrean job dan session login pengguna.
Memantau
redis-cli INFO memory # pemakaian memori
redis-cli INFO stats # keyspace_hits dan keyspace_misses
redis-cli --bigkeys # kunci yang paling besar
Rasio hit yang rendah menandakan kunci terlalu bervariasi atau TTL terlalu pendek. Atur maxmemory dan kebijakan maxmemory-policy (misalnya allkeys-lru untuk server khusus cache) agar Redis tidak kehabisan memori.
Kesalahan yang Sering Terjadi
- Cache tanpa invalidasi, sehingga admin mengubah data tapi pengunjung tetap melihat versi lama.
Cache::flush()di production yang ikut menghapus session dan job karena satu database Redis.- Cache untuk menutupi query buruk. Perbaiki query dan index dulu; caranya di MySQL performance tuning.
- Redis terbuka ke internet tanpa password. Ikat ke localhost atau jaringan privat.
Langkah Berikutnya
Redis juga dipakai untuk fitur real-time dan scaling WebSocket, dibahas di Laravel Reverb. Untuk struktur aplikasi yang mudah diberi cache, lihat Laravel 12 best practices.