Bir ekip “site yavaş” diye Redis cache ekledi. Bir hafta sonra destek kuyruğu doldu: “Fiyatı güncelledim ama eski fiyat görünüyor.” Cache yavaşlığı çözmüştü — ve sessizce yeni bir problem yaratmıştı.
Cache eklemek bedava bir performans kazancı değildir. Tazeliği hıza takas etmektir; bu takası bilerek yapmadıysanız, fatura bir bug olarak geri gelir.
Cache bir tutarlılık ödünüdür
Bir değeri cache’lediğiniz an şunu kabul etmiş olursunuz: birileri, bir süreliğine, eski veriyi görebilir. Cache hiçbir zaman “daha hızlı veritabanı” değildir; “kabul edilmiş bayatlık karşılığında hız”dır.
Bu yüzden ilk soru teknik değil: bu veri ne kadar bayat olabilir? Cevabı “hiç” olan bir veri — bir hesap bakiyesi, bir stok adedi — cache’lenmeden önce iki kez düşünülmelidir.
Önce sorulacak sorular
Redis’i açmadan önce:
- Bu gerçekten bir okuma darboğazı mı? “Site yavaş” bir hipotezdir, ölçüm değil. Yavaşlığın kaynağını görmeden cache eklemek, bilinmeyen bir şeyin üstünü örtmektir.
- Yavaşlık aslında eksik bir indeks mi? Cache, kötü bir sorgunun üstünü örter ama onu çözmez. Bir
CREATE INDEX’in çözeceği şeyi cache’le gizlemek, problemi taşımaktır — veri yoğunluklu sistemlerdeki yanlış kırılma noktası tam olarak budur. - Bu veri ne kadar bayat kalabilir? Cevap, hangi stratejiyi seçeceğinizi belirler.
Invalidation neden zor
Yazılımın iki zor probleminden biri olarak anılır cache invalidation — ve abartı değil. Cache’i koymak kolaydır; onu doğru anda temizlemek zordur.
Çünkü bir cache değeri, onu etkileyen her yazma yolunda temizlenmelidir. Ürün fiyatı yalnızca “ürünü düzenle” ekranından değil; toplu fiyat güncellemesinden, bir indirim işinden, bir admin script’inden de değişir. Bu yolların hepsini bulup cache’i temizlemek — işte zor olan bu. Bir tanesini kaçırırsanız, yazının başındaki destek talebini alırsınız.
İki strateji
Pratikte iki yol var:
- TTL tabanlı. Değere bir ömür biçersiniz — 60 saniye, 5 dakika. Süre dolunca cache kendini tazeler. Basit, sağlam, her yazma yolunu bilmeyi gerektirmez. Karşılığında: TTL süresi kadar bayatlık kabul edersiniz.
- Açık invalidation. Veri değiştiğinde cache’i elle silersiniz. Kesin ve tazedir — ama yalnızca her yazma yolunu eksiksiz yakalarsanız.
Varsayılanım TTL’dir. Sıkıcı, öngörülebilir ve unutulan bir yazma yolu yüzünden sessizce bozulmaz. Açık invalidation’a yalnızca bayatlık gerçekten kabul edilemezken ve yazma yollarının sayısı sınırlı ve bilinirken geçerim. Çoğu zaman ikisi birlikte kullanılır: kısa bir TTL bir güvenlik ağı olarak, açık invalidation hız için.
Cache yazmayı azaltmaz
Sık yapılan bir hata: yazma yükü altındaki bir sistemi cache ekleyerek kurtarmaya çalışmak. Cache okuma yükünü azaltır; yazma yüküne hiçbir etkisi yoktur — aksine, invalidation’ın kendisi ek yazma işidir. Probleminiz yazma tarafındaysa, cache yanlış araçtır.
Pratik kalıplar
- Cache-aside. Oku: önce cache’e bak, yoksa veritabanından al ve cache’e yaz. En yaygın ve en anlaşılır kalıp.
- Stampede koruması. Popüler bir anahtarın TTL’i dolduğu an yüzlerce istek aynı anda veritabanına gider. Cache miss’te kısa bir lock ile yalnızca bir isteğin veritabanına gitmesini sağlayın.
- Anahtar disiplini. Cache anahtarlarını namespace’leyin — shared Redis namespace izolasyonu notundaki kalıp, cache anahtarları için de geçerlidir.
Cache, yavaş bir sistemin çözümü değil; ölçülmüş bir okuma darboğazının, bilinçli bir tutarlılık ödünüyle hafifletilmesidir. Invalidation planı olmadan eklenen cache, hızlandırdığından fazlasını borç olarak geri alır.
Cache koymadan önce sorun: bu veri ne kadar eski olabilir — ve onu kim temizleyecek?

Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.