Merhaba arkadaşlar, bugün sizlere Laravel'de projemin canını acıtan bir sorundan ve nasıl kurtulduğumdan bahsedeceğim. Proje büyüdükçe, özellikle ana sayfadaki karmaşık raporlama verilerini çeken query'ler, database sunucusunu adeta yemeye başlamıştı. Sayfa açılışları 3-4 saniyeyi buluyordu ve bu durum beni çıldırtmıştı. İşte tam bu noktada Laravel'in güçlü cache'leme mekanizmaları imdadıma yetişti.
Database'in Yükünü Hafifletmek
Sorun şuydu: Kullanıcı panelinin dashboard'unda, son 30 günün istatistikleri, en popüler içerikler ve çeşitli aggregasyon verileri gösteriliyordu. Her kullanıcı sayfayı her yenilediğinde, aynı ağır query'ler tekrar tekrar çalıştırılıyordu. Bu, hem gereksiz bir yüktü hem de kullanıcı deneyimini mahvediyordu. Çözüm ise basit ve etkiliydi: Sık değişmeyen verileri cache'lemek.
Laravel'de cache'leme yapmanın birden fazla yolu var (file, redis, memcached). Ben performans için Redis driver'ını kullanmayı tercih ettim. İlk adım, config/cache.php dosyasında default driver'ı 'redis' olarak ayarlamak.
Cache Facade ile Temel Kullanım
En temel haliyle, bir veriyi cache'lemek ve çekmek için `Cache` facade'unu kullanıyoruz. İşte benim dashboard controller'ımda yaptığım ilk iyileştirme:
Buradaki Cache::remember metodu sihirli gücünü gösteriyor. İlk parametre cache anahtarı, ikincisi saniye cinsinden ömür (600 saniye = 10 dakika), üçüncüsü ise cache'te veri yoksa çalıştırılacak ve döndürülecek değeri üreten closure. Bu sayede, kullanıcı 10 dakika içinde sayfayı 100 kere yenilese bile, o ağır sorgular sadece ilk seferde çalışacak. Sonrasında veri Redis'ten hızlıca getirilecek.
Model Query'lerine Özel Cache
Peki ya bir model için yapılan belirli query'leri global olarak cache'lemek istersek? Laravel bunun için de güzel bir yöntem sunuyor. Örneğin, sitenizde "En Çok Yorum Alan Yazılar" gibi bir bölüm her sayfada sidebar'da duruyor olabilir. Bunu her seferinde veritabanına sormak yerine, modelinize özel bir scope yazabiliriz:
Artık controller'da sadece `Post::mostCommented()->get()` yazarak, sonucu 1 saat boyunca cache'lenmiş bir query çalıştırmış oluyoruz. Veri değiştiğinde (yeni yorum eklendiğinde) cache'i temizlemeyi unutmamak gerekiyor tabii.
Cache'in Temizlenme Zamanı
Cache'lemenin en kritik noktası, veri değiştiğinde eski cache'i geçersiz kılmaktır. Aksi takdirde kullanıcılar eski veriyi görmeye devam eder. Bunun için genellikle model event'larını (Observer) kullanıyorum. Örneğin, bir sipariş oluştuğunda veya durumu değiştiğinde, ilgili kullanıcının dashboard cache'ini temizleyelim:
Cache::forget[/COLOR] metodu ile spesifik bir anahtarı silebiliyoruz. Bir sonraki sayfa isteğinde, `remember` metodu cache'te veri bulamayacağı için closure'u tekrar çalıştıracak ve taze veriyi alıp yeniden cache'leyecek.
Sonuç olarak, bu basit tekniklerle database sorgu sayımı %70'lere varan oranda düşürdüm ve sayfa yükleme sürelerini saniyelerden milisaniyelere indirdim. Laravel'in cache sisteminin sadeliği ve gücü gerçekten takdire şayan.
Peki sizin Laravel projelerinizde cache'leme için favori taktiğiniz nedir? Özellikle çok dinamik, sık güncellenen verilerde cache invalidation stratejinizi nasıl kuruyorsunuz? Redis dışında memcached veya dosya cache'i deneyen oldu mu, performans karşılaştırmalarınız var mı? Yorumlarda deneyimlerinizi paylaşın, tartışalım!
Sorun şuydu: Kullanıcı panelinin dashboard'unda, son 30 günün istatistikleri, en popüler içerikler ve çeşitli aggregasyon verileri gösteriliyordu. Her kullanıcı sayfayı her yenilediğinde, aynı ağır query'ler tekrar tekrar çalıştırılıyordu. Bu, hem gereksiz bir yüktü hem de kullanıcı deneyimini mahvediyordu. Çözüm ise basit ve etkiliydi: Sık değişmeyen verileri cache'lemek.
Laravel'de cache'leme yapmanın birden fazla yolu var (file, redis, memcached). Ben performans için Redis driver'ını kullanmayı tercih ettim. İlk adım, config/cache.php dosyasında default driver'ı 'redis' olarak ayarlamak.
En temel haliyle, bir veriyi cache'lemek ve çekmek için `Cache` facade'unu kullanıyoruz. İşte benim dashboard controller'ımda yaptığım ilk iyileştirme:
PHP:
use Illuminate\Support\Facades\Cache;
class DashboardController extends Controller
{
public function index()
{
$cacheKey = 'user_dashboard_stats_' . auth()->id();
$stats = Cache::remember($cacheKey, 600, function () {
return [
'monthly_orders' => Order::where('created_at', '>=', now()->subDays(30))->count(),
'top_products' => Product::withCount('orders')->orderBy('orders_count', 'desc')->take(5)->get(),
'revenue' => Payment::whereStatus('completed')->sum('amount')
];
});
return view('dashboard', compact('stats'));
}
}
Buradaki Cache::remember metodu sihirli gücünü gösteriyor. İlk parametre cache anahtarı, ikincisi saniye cinsinden ömür (600 saniye = 10 dakika), üçüncüsü ise cache'te veri yoksa çalıştırılacak ve döndürülecek değeri üreten closure. Bu sayede, kullanıcı 10 dakika içinde sayfayı 100 kere yenilese bile, o ağır sorgular sadece ilk seferde çalışacak. Sonrasında veri Redis'ten hızlıca getirilecek.
Peki ya bir model için yapılan belirli query'leri global olarak cache'lemek istersek? Laravel bunun için de güzel bir yöntem sunuyor. Örneğin, sitenizde "En Çok Yorum Alan Yazılar" gibi bir bölüm her sayfada sidebar'da duruyor olabilir. Bunu her seferinde veritabanına sormak yerine, modelinize özel bir scope yazabiliriz:
PHP:
use Illuminate\Support\Facades\Cache;
class Post extends Model
{
public function scopeMostCommented($query, $limit = 5)
{
$cacheKey = 'most_commented_posts_' . $limit;
$postIds = Cache::remember($cacheKey, 3600, function () use ($limit) {
return DB::table('comments')
->select('post_id', DB::raw('count() as total'))
->groupBy('post_id')
->orderBy('total', 'desc')
->limit($limit)
->pluck('post_id');
});
return $query->whereIn('id', $postIds)->get();
}
}
Artık controller'da sadece `Post::mostCommented()->get()` yazarak, sonucu 1 saat boyunca cache'lenmiş bir query çalıştırmış oluyoruz. Veri değiştiğinde (yeni yorum eklendiğinde) cache'i temizlemeyi unutmamak gerekiyor tabii.
Cache'lemenin en kritik noktası, veri değiştiğinde eski cache'i geçersiz kılmaktır. Aksi takdirde kullanıcılar eski veriyi görmeye devam eder. Bunun için genellikle model event'larını (Observer) kullanıyorum. Örneğin, bir sipariş oluştuğunda veya durumu değiştiğinde, ilgili kullanıcının dashboard cache'ini temizleyelim:
PHP:
class OrderObserver
{
public function saved(Order $order)
{
$cacheKey = 'user_dashboard_stats_' . $order->user_id;
Cache::forget($cacheKey);
}
}
Cache::forget[/COLOR] metodu ile spesifik bir anahtarı silebiliyoruz. Bir sonraki sayfa isteğinde, `remember` metodu cache'te veri bulamayacağı için closure'u tekrar çalıştıracak ve taze veriyi alıp yeniden cache'leyecek.
Sonuç olarak, bu basit tekniklerle database sorgu sayımı %70'lere varan oranda düşürdüm ve sayfa yükleme sürelerini saniyelerden milisaniyelere indirdim. Laravel'in cache sisteminin sadeliği ve gücü gerçekten takdire şayan.
Peki sizin Laravel projelerinizde cache'leme için favori taktiğiniz nedir? Özellikle çok dinamik, sık güncellenen verilerde cache invalidation stratejinizi nasıl kuruyorsunuz? Redis dışında memcached veya dosya cache'i deneyen oldu mu, performans karşılaştırmalarınız var mı? Yorumlarda deneyimlerinizi paylaşın, tartışalım!