Caching Stratejileri Nedir? Performans Artırma Rehberi
Kullanıcılarınız her istekte veritabanını mı zorluyor? Sayfa yükleme süreleri uzun mu? Caching ile sık erişilen verileri hızlı katmanlarda saklayarak uygulamanızın performansını dramatik şekilde artırın.
Cache Nedir?
Cache (önbellek), sık erişilen verilerin daha hızlı bir katmanda geçici olarak saklanmasıdır. Amaç, yavaş veri kaynaklarına (veritabanı, API, disk) erişim sayısını azaltmaktır.
Cache yok: İstek → Veritabanı (50ms) → Yanıt
Cache var: İstek → Redis (0.5ms) → Yanıt
Cache Katmanları
Kullanıcı → Browser Cache → CDN → API Cache → DB Cache → Veritabanı
(en hızlı) (en yavaş)
| Katman | Hız | Örnek | |--------|-----|-------| | Browser Cache | <1ms | Static dosyalar, API yanıtları | | CDN | 5-20ms | Resimler, CSS, JS | | Application Cache | 0.5-2ms | Redis, Memcached | | Database Cache | 5-10ms | Query cache, buffer pool |
Caching Stratejileri
1. Cache-Aside (Lazy Loading)
En yaygın strateji. Uygulama cache'i kendisi yönetir:
async function getUser(userId: string) {
// 1. Önce cache'e bak
const cached = await redis.get(`user:${userId}`);
if (cached) return JSON.parse(cached);
// 2. Cache miss — DB'den al
const user = await db.users.findById(userId);
// 3. Cache'e yaz
await redis.set(`user:${userId}`, JSON.stringify(user), 'EX', 3600);
return user;
}
Avantaj: Sadece istenen veri cache'lenir Dezavantaj: İlk istek yavaş (cache miss)
2. Write-Through
Her yazma işleminde cache de güncellenir:
async function updateUser(userId: string, data: UserData) {
// 1. DB'ye yaz
await db.users.update(userId, data);
// 2. Cache'i de güncelle
await redis.set(`user:${userId}`, JSON.stringify(data), 'EX', 3600);
}
Avantaj: Cache her zaman güncel Dezavantaj: Her yazma işlemi iki katına çıkar
3. Write-Behind (Write-Back)
Önce cache'e yaz, sonra arka planda DB'ye yaz:
İstek → Cache'e yaz (hızlı yanıt) → Arka plan: DB'ye yaz
Avantaj: Yazma çok hızlı Dezavantaj: Veri kaybı riski (cache çökerse)
4. Read-Through
Cache katmanı otomatik olarak DB'den yükler:
İstek → Cache → (miss?) → Cache otomatik DB'den alır → Yanıt
Cache Invalidation
"Bilgisayar biliminde iki zor şey vardır: cache invalidation ve isimlendirme." — Phil Karlton
TTL (Time-To-Live)
await redis.set('user:42', data, 'EX', 3600); // 1 saat sonra otomatik sil
Event-Based Invalidation
async function updateUser(userId: string, data: UserData) {
await db.users.update(userId, data);
await redis.del(`user:${userId}`); // Cache'i sil, sonraki okumada yeniden yüklensin
}
Pattern-Based
// Tüm kullanıcı cache'lerini temizle
const keys = await redis.keys('user:*');
if (keys.length) await redis.del(...keys);
CDN Cache
Statik dosyalar için Content Delivery Network:
Kullanıcı (İstanbul) → CDN Edge (İstanbul) → Hızlı yanıt
Kullanıcı (New York) → CDN Edge (New York) → Hızlı yanıt
Cache-Control Header
Cache-Control: public, max-age=31536000, immutable → Statik dosyalar (1 yıl)
Cache-Control: private, no-cache → Kullanıcıya özel veriler
Cache-Control: no-store → Hassas veriler (asla cache'leme)
Cache Tutarlılık Problemleri
Stale Data
Cache'deki veri eskimiş olabilir. TTL ile sınırlayın.
Thundering Herd
TTL dolduğunda binlerce istek aynı anda DB'ye gider:
// Çözüm: Mutex lock
async function getWithLock(key: string) {
const cached = await redis.get(key);
if (cached) return JSON.parse(cached);
const lock = await redis.set(`lock:${key}`, '1', 'NX', 'EX', 5);
if (lock) {
const data = await db.query(key);
await redis.set(key, JSON.stringify(data), 'EX', 3600);
return data;
}
// Lock alınamazsa kısa bekle ve tekrar dene
await sleep(100);
return getWithLock(key);
}
Best Practices
- Doğru TTL seçin — Çok kısa: avantaj yok, çok uzun: stale data
- Cache key standardı —
entity:id:fieldformatı (user:42:profile) - Warm-up yapın — Uygulama başlarken kritik verileri önceden cache'leyin
- Monitoring — Hit/miss oranını izleyin (%90+ hit rate hedefleyin)
- Boyutu sınırlayın — Eviction policy belirleyin (LRU, LFU)
- Hassas veriyi cache'lemeyin — Şifreler, tokenlar asla cache'te olmamalı
Sonuç
Caching, uygulama performansını artırmanın en etkili yollarından biridir. Doğru strateji ve invalidation yaklaşımıyla 10x-100x hız kazanımı sağlayabilirsiniz. Ancak tutarlılık sorunlarına dikkat edin — cache invalidation gerçekten zordur.
Caching stratejilerini LabLudus platformunda pratik yaparak öğrenin.