Cache Stratejileri — Defter Ne Zaman Yalan Söyler?
Önce şunu oku: Spring Cache — @Cacheable Kimin Cevabını Hatırlıyor?
30 saniyede özet
Cache, uzaktaki veritabanının yanında duran hızlı bir defterdir. Okurken önce deftere bakılır, yazarken defterdeki not güncellenmez, silinir. Yine de eski bir not araya sızabilir; TTL onun ne kadar yaşayacağını sınırlar.
Mahalle bakkalı her fiyat sorusunda arkadaki depoya yürümez. Tezgâhta bir defter tutar: bir kez baktığı fiyatı oraya yazar, sonra defterden söyler.
Adım adım oku
- Müşteri çayın fiyatını sorar; defterde yok, bakkal depoya gider ve fiyatı deftere yazar.
- Sonraki müşteriye fiyat defterden, hemen söylenir.
- Depoda fiyat değişince defterdeki not silinir.
- Yeni soru defterde bir şey bulamaz, depodan yeni fiyatı getirir ve deftere yazar.
-
Bayt: Müşteri kasada şikâyet ediyor: ürün sayfası bir fiyat söylüyor, sepet başka!
-
Sen: Fiyatı değiştirince cache'i de güncellemiyor muyduk?
-
Bayt: Güncelliyoruz. Demek ki bir yerde sıra karışıyor...
-
Bayt: Defter ne zaman yalan söyler, önce onu anlayalım.
Cache-aside: önce deftere bak
cache-asideUygulamanın önce cache'e baktığı, bulamazsa veritabanından okuyup cache'e koyduğu düzen. Cache veritabanının yanında durur; düşerse uygulama veritabanından devam eder.Sözlükte gör → düzeninde uygulama önce cache’e bakar. Bulursa (hit) hemen döner; bulamazsa (miss) veritabanından okur, cache’e koyar ve döner.
oku: cache.get(key) ──bulundu──→ döndür └─yok──→ db.read(key) → cache.set(key, değer, TTL) → döndürCache her şeye değmez. Çok okunan, az değişen ve biraz eski görünmesi dert olmayan veri iyi adaydır: ürün sayfası, kategori listesi, döviz kuru ekranı. Ödemede kullanılacak fiyat ise veritabanından okunur.
Kafam karıştı, daha basit anlat
Önce deftere bak. Yoksa depoya git, fiyatı deftere yaz. Defter hızlıdır ama bazen geride kalır.
Cache-aside düzeninde cache'i kim doldurur?
Yazınca defter ne olacak?
Veri değişince cache’e ne olacağına dair birkaç düzen var. Write-through: her yazma hem veritabanına hem cache’e aynı anda gider. write-behindYazmanın önce cache'e yapılıp veritabanına sonradan toplu aktarıldığı düzen. Yazma hızlanır; cache düşerse henüz aktarılmamış değişiklikler kaybolabilir.Sözlükte gör →: yazma önce cache’e gider, veritabanına sonra toplu yazılır; hızlıdır ama cache düşerse yazma kaybolabilir.
Cache-aside kullanan çoğu sistem ise yazarken ya cache’teki değeri günceller ya da girdiyi siler. İkisi aynı görünür.
Fiyat 100. Ayşe 120 yazıyor, Mert hemen ardından 130. İkisi de commit'ten sonra cache.set yapıyor, ama Ayşe'ninki ağda gecikip en son varıyor. Ekran ne gösterir? Cevabı göster
120, veritabanında 130 varken. Cache’e yazmalar veritabanına yazmaların tersi sırayla vardı ve son gelen eski değeri taşıyordu. Fiyat bir daha değişmezse cache hep yanlış kalır.
Girdiyi silmek bu yarışı kapatır. İki silme hangi sırayla gelirse gelsin sonuç aynıdır: girdi yoktur ve sonraki okuma veritabanından taze değeri getirir.
Kafam karıştı, daha basit anlat
Deftere yeni fiyatı yazmak yerine eski notu sil. Silmek hangi sırayla gelirse gelsin aynı sonucu verir.
Write-behind (write-back) düzeninin en büyük riski hangisi?
Veri değişince cache'teki değeri güncellemek yerine girdiyi silmek neden daha güvenli?
Satır satır: yavaş okuyan
Eski fiyat cache'e nasıl geri girer?
Price find(String sku) { Price cached = cache.get(sku); if (cached != null) return cached; Price fresh = db.findPrice(sku); cache.set(sku, fresh, TTL); return fresh;} void change(String sku, Price price) { db.updatePrice(sku, price); // commits cache.delete(sku);}Debug
okuyan Girdinin süresi az önce dolmuş. Cache boş: miss.
- cache
- = yok
- db
- = 100
Sol/sağ ok tuşlarıyla da gezebilirsin.
Bu yarış nadirdir: okuyanın veritabanı okuması ile cache’e yazması arasındaki boşluk, yazanın bütün işinden uzun sürmelidir. Nadir ama imkânsız değil.
Bu yüzden her girdiye bir TTLTime to live: bir cache girdisinin ne kadar süre geçerli sayılacağı. Süre dolunca girdi silinir ve sonraki okuma kaynağa gider; o süre boyunca eski veri görülebilir.Sözlükte gör → verilir. TTL yarışı önlemez; eski değerin en fazla ne kadar yaşayacağını söyler.
Olaylar bu sırayla gerçekleşiyor. Ne yazdırılır?
Yazan commit'ten sonra cache'i siliyor. Yine de nadiren eski fiyat cache'e geri giriyor. Bu açığı sınırlamanın en basit yolu hangisi?
Kendin gör
Başlangıçta fiyat hem veritabanında hem cache’te 100. Yazan fiyatı değiştirirken aynı anda başka bir şey oluyor.
Cache ne zaman yalan söyler?
Tohum 1Başlangıç: veritabanında da cache'te de fiyat 100.
Oynat ya da adımla.
Şu an ne oldu?
Fiyat değişiyor, cache yanında duruyor
Veritabanında 100 yazıyor. Yazan fiyatı değiştirecek; cache sonunda hangi fiyatı gösterecek?
Görevler0/3
Cache'in veritabanından farklı bir fiyatı süresiz göstermesini sağlaaçık
İpucu
TTL kapalıyken iki yazanın cache'e değer koymasına izin ver.
İki yazan yarışırken cache doğru fiyatı göstersinaçık
İpucu
Yazan cache'e değer koymasın.
Yavaş okuyanın cache'e koyduğu eski fiyat kendiliğinden temizlensinaçık
İpucu
Hiçbir yazma stratejisi bunu önlemez. Girdiye bir ömür ver.
Olay günlüğü (0)
Henüz olay yok. Oynat veya adımla.
- Varsayılanı oynat. İki yazan, ikisi de cache’e değer koyuyor: cache 120, veritabanı 130. TTL yok, yanlışlık süresiz.
- Yazarken “DB’ye yaz, sonra cache’ten sil” seç. Aynı yarış, ama sonraki okuma 130’u getiriyor.
- “Yavaş bir okuyan araya giriyor” seç. Üç stratejinin üçünde de eski fiyat geri giriyor. TTL’i aç ve farkı gör.
Deploy sonrası cache ısıtıldı: 50.000 girdi aynı dakikada, hepsi 10 dakikalık TTL'le yazıldı. Tam 10 dakika sonra veritabanı yükü sıçrıyor. En uygun düzeltme hangisi?
Tuzaklar
Hepsi aynı anda bitiyor. Deploy sonrası ısıtılan binlerce girdi aynı TTL’le yazılırsa aynı saniyede biter ve hepsi birden veritabanına gider. Süreye rastgele küçük bir pay eklemek bitişleri zamana yayar.
Çok okunan tek girdi bitiyor. O anda yüzlerce istek aynı sorguyu çalıştırır: cache stampedeSık okunan bir cache girdisi silindiği anda çok sayıda isteğin aynı değeri aynı anda kaynaktan hesaplamaya çalışması. Veritabanına ani bir yük bindirir.Sözlükte gör →. Çözüm, girdiyi tek bir isteğin yüklemesi ve diğerlerinin onu beklemesidir; Spring Cache dersindeki sync = true bunun bir örneği.
Olmayan anahtarlar. Var olmayan bir ürün hiç cache’e girmez ve her soru veritabanına gider. “Yok” cevabı da kısa bir süreyle saklanır.
Kafam karıştı, daha basit anlat
Notlar aynı anda silinmesin, çok sorulan notu tek kişi yenilesin, “böyle bir ürün yok” da deftere yazılsın.
Her özellik hangi düzene ait?
Derinleş · Ürün fiyatı: okuma, yazma ve commit sonrası silme 3 dosya · ~78 satır · ilk okumada atlayabilirsin
Kendini sına
Önce hızlı bir ısınma: puan yok, kayıt yok. Sonra asıl sorular.
Cache-aside'da cache'i okuyan taraf doldurur.
Bu senaryoda hangi yolu seçersin?
Aklında kalacak üç şey
- 1 Cache-aside'da okuyan önce cache'e bakar, yoksa veritabanından okuyup cache'e koyar. Cache'in bilgisi hep veritabanının bir kopyasıdır ve geride kalabilir.
- 2 Yazarken cache'teki değeri güncellemek, iki yazan yarışınca eski değeri kalıcı bırakabilir. Commit'ten sonra girdiyi silmek bu yarışı kapatır.
- 3 Hiçbir yazma stratejisi yavaş bir okuyanın eski değeri geri koymasını tamamen önlemez. TTL güvenlik ağıdır ve girdiler aynı anda bitmesin diye süreye rastgele bir pay eklenir.
4 kart sonraki derste seni bekliyor
Bu dersin üstüne kurulanlar
Bunlar bu dersi temel alıyor; hazır olduğunda devam edebilirsin.
- System Design & Dağıtık SistemlerURL Kısaltıcı Tasarımı — Parçaları Tek Sistemde BirleştirmekKısa kodu adresin hash'inden kesip alıyorsun. Milyarlarca linkte bir gün ne olur?Derse git
- System Design & Dağıtık SistemlerBloom Filter — "Kesinlikle Yok" mu, "Belki Var" mı?Milyonlarca kaydı kontrol etmen gerekiyor ama hepsini belleğe sığdıramıyorsun. Yalnızca birkaç bit yeter mi?Derse git