---
title: 'Tipik Kullanım Senaryoları'
source: 'https://academia.sh/tr/kurslar/bellek-ici-depolar/tipik-kullanim-senaryolari'
course: 'Bellek İçi Depolar ve Önbellek Sistemleri'
language: tr
updated: '2026-08-17T18:08:57+00:00'
license: 'CC BY-SA 4.0'
---

# Tipik Kullanım Senaryoları

Katalog önbelleği, oturum kaydı, hız sınırı ve sıralama tablosunun bellek içi deponun yapılarına oturtulması: her senaryonun hangi yapıyla kurulduğu, giriş başına kaç bayt tuttuğu ve o baytın karşılığında hangi erişimi satın aldığı.

Önceki ders yayımla–abone ol yolunu ölçtü ve bir sınırla bitti: o yol hiçbir şey saklamadığı
için 49 bayt tutuyordu, karşılığında kopan abonenin 700 olayı geri gelmiyordu. Bu, bu kursun
tekrar eden sorusunun tek bir örneğiydi. Aynı soru deponun günlük işlerinin hepsinde sorulur.

Bu ders kütüphane sisteminin dört tipik işini alır — katalog önbelleği, oturum kaydı, hız sınırı,
popüler kitap sıralaması — ve her birini tek bir soruya indirger: **hangi yapıyla kurulur ve kaç
bayt tutar.** Önbellek stratejisinin ne olacağı, hız sınırının hangi algoritmayla işleyeceği
burada tartışılmaz; o seçimler başka kurslarda ölçüldü. Burada ölçülen şey yapının kendisidir.

## Ortak Maliyet Modeli

Dört hesap da aynı sayma kuralını kullanır (**BK13**): her giriş için 16 bayt işaretçi/uzunluk
payı, karma yapıda her alan için 8 bayt ek pay, sıralı kümede her üye için 24 bayt dizin düğümü
payı, her sayısal değer için 8 bayt. Anahtarların ve dizgi değerlerinin baytı gerçek uzunluktan
okunur. Bu model bir ürünün iç yerleşimi değil, kendi deposunun sayma sözleşmesidir; önemli
olan iki seçeneğin **aynı** kuralla sayılmasıdır.

## Katalog Önbelleği ve Oturum Kaydı

İlk iki senaryo aynı yapıyı, karma yapıyı, iki farklı nedenle seçer. Katalog önbelleğinde soru
kaydın bütün hâlinde mi yoksa alan alan mı tutulacağıdır. Oturum kaydında soru, kayıtların ne
kadar süreyle tutulacağıdır: oturum verisi süre sonuyla birlikte kurulur ve bellek, açılan oturum
sayısıyla değil **aynı anda canlı** oturum sayısıyla ölçeklenir.

```js
// senaryo-katalog-oturum.mjs — katalog onbellegi ve oturum kaydi: hangi yapi, kac bayt
const EK_GIRIS = 16, EK_ALAN = 8, SAYI = 8;        // kendi maliyet modelim (giris/alan/sayi payi)
const b = (s) => Buffer.byteLength(String(s));
const alanBayt = (ad, deger) =>                    // karma yapida bir alanin maliyeti
  b(ad) + (typeof deger === "number" ? SAYI : b(deger)) + EK_ALAN;

function kitaplar(adet) {
  let tohum = 20250731;
  const rast = () => ((tohum = (tohum * 1103515245 + 12345) % 2147483648) / 2147483648);
  const etiketler = ["roman", "tarih", "cocuk", "bilim"];
  return Array.from({ length: adet }, (_, i) => ({
    kitapId: i + 1, baslik: `Kitap ${i + 1}`,
    yazar: `Yazar ${Math.floor(rast() * 120) + 1}`,
    sube: Math.floor(rast() * 3) + 1, rafta: Math.floor(rast() * 5),
    etiket: etiketler[Math.floor(rast() * 4)],
  }));
}

// --- Senaryo 1: katalog onbellegi. Ayni kayit iki yapiyla tutulur.
const kayitlar = kitaplar(400);
let dizgiBayt = 0, karmaBayt = 0, dizgiYazma = 0, karmaYazma = 0;
for (const k of kayitlar) {
  const anahtar = `kitap:${k.kitapId}`;
  const govde = JSON.stringify(k);
  dizgiBayt += b(anahtar) + b(govde) + EK_GIRIS;   // tek dizgi: govde butun hâlinde
  karmaBayt += b(anahtar) + EK_GIRIS +             // karma yapi: alan alan
    Object.entries(k).reduce((t, [ad, d]) => t + alanBayt(ad, d), 0);
}
for (let i = 0; i < 1000; i += 1) {                // 1000 raf guncellemesi: yalniz `rafta` degisir
  const k = kayitlar[i % kayitlar.length];
  dizgiYazma += b(JSON.stringify(k));              // dizgide butun govde yeniden yazilir
  karmaYazma += SAYI;                              // karmada yalniz o alanin degeri
}
console.log("katalog onbellegi (400 kitap)");
console.log(`  dizgi  : tutulan=${dizgiBayt} bayt  giris basina=${Math.round(dizgiBayt / 400)}` +
  `  1000 guncellemede yazilan=${dizgiYazma} bayt`);
console.log(`  karma  : tutulan=${karmaBayt} bayt  giris basina=${Math.round(karmaBayt / 400)}` +
  `  1000 guncellemede yazilan=${karmaYazma} bayt`);

// --- Senaryo 2: oturum kaydi. Karma yapi + sure sonu; sure sonu etkin oturumu sinirlar.
const DAKIKA = 720, DK_GIRIS = 25, OMUR = 30;      // 12 saat, dakikada 25 giris, 30 dk sure sonu
const oturumAlanlari = { kullaniciId: 1, sube: 1, rol: "uye", sonErisim: 1 };
const oturumBayt = b("oturum:") + 32 + EK_GIRIS +  // anahtar: onek + 32 karakterlik kimlik
  Object.entries(oturumAlanlari).reduce((t, [ad, d]) => t + alanBayt(ad, d), 0);
const canli = new Map();                           // kimlik -> sonGecerlilik (dakika)
let zirveCanli = 0, acilan = 0;
for (let dk = 1; dk <= DAKIKA; dk += 1) {
  for (const [kimlik, son] of canli) if (son <= dk) canli.delete(kimlik);   // sure sonu temizler
  for (let i = 0; i < DK_GIRIS; i += 1) canli.set(`o${acilan++}`, dk + OMUR);
  zirveCanli = Math.max(zirveCanli, canli.size);
}
console.log("oturum kaydi (12 saat)");
console.log(`  giris basina=${oturumBayt} bayt  acilan oturum=${acilan}  zirve canli=${zirveCanli}`);
console.log(`  sure sonu var : tutulan=${zirveCanli * oturumBayt} bayt`);
console.log(`  sure sonu yok : tutulan=${acilan * oturumBayt} bayt` +
  `  (${(acilan / zirveCanli).toFixed(1)} kat)`);
```

```
katalog onbellegi (400 kitap)
  dizgi  : tutulan=46115 bayt  giris basina=115  1000 guncellemede yazilan=90454 bayt
  karma  : tutulan=60623 bayt  giris basina=152  1000 guncellemede yazilan=8000 bayt
oturum kaydi (12 saat)
  giris basina=141 bayt  acilan oturum=18000  zirve canli=750
  sure sonu var : tutulan=105750 bayt
  sure sonu yok : tutulan=2538000 bayt  (24.0 kat)
```

Katalog satırlarındaki takas nettir. Karma yapı 14.508 bayt fazla tutuyor (giriş başına 115
yerine 152), çünkü her alanın adı ve her alanın ek payı ayrı ayrı ödeniyor. Satın aldığı şey
ikinci sütundadır: bin raf güncellemesinde dizgi biçimi 90.454 bayt yeniden yazarken karma yapı
8.000 bayt yazıyor. Kayıt bütün hâlinde tutulduğunda tek bir sayının değişmesi bütün gövdenin
yeniden yazılması demektir; ayrıca gövdenin çözülüp yeniden kurulması gerekir.

Seçim, kaydın nasıl kullanıldığına bağlıdır. Kayıt her zaman bütün hâlinde okunuyor ve seyrek
güncelleniyorsa dizgi biçimi daha az bayt tutar ve tek erişimde biter. Alanları ayrı ayrı okunuyor
ya da güncelleniyorsa karma yapının fazladan 37 baytı, her güncellemede kazanılan 82 bayt yazmayla
karşılanır.

Oturum satırlarındaki takas başka bir eksende. Giriş başına 141 bayt ile on iki saatte açılan
18.000 oturumun tamamı tutulsa 2.538.000 bayt gerekirdi. Süre sonu, aynı anda canlı olan oturumu
750'de tutuyor ve maliyeti 105.750 bayta indiriyor: yirmi dört kat. Burada bellek, kullanıcı
sayısıyla değil **oturum ömrüyle** ölçeklenir. Kaybedilen şey de bellidir: süresi dolan oturumun
verisi geri getirilemez, kullanıcı yeniden kimlik doğrular (**BK14**).

## Hız Sınırı ve Sıralama Tablosu

Son iki senaryo aynı sorunun iki ucudur: bir sayının kendisi yeterli mi, yoksa sayıyı oluşturan
tek tek girişler de gerekli mi. Hız sınırında sayaç yalnız pencerenin toplamını tutar; sıralı
küme her isteğin anını ayrı bir üye olarak tutar. Sıralama tablosunda karma yapı yalnız ödünç
sayılarını tutar; sıralı küme bunların üstüne sıralı bir dizin taşır.

```js
// senaryo-hiz-siralama.mjs — hiz siniri ve siralama tablosu: hangi yapi, kac bayt, kac giris
const EK_GIRIS = 16, EK_ALAN = 8, EK_DIZIN = 24, SAYI = 8;   // ayni maliyet modeli
const b = (s) => Buffer.byteLength(String(s));

// --- Senaryo 3: hiz siniri. Sayac pencerenin toplamini, sirali kume tek tek anlari tutar.
const KULLANICI = 2000, SINIR = 60;                // dakikada 60 istek
let sayacBayt = 0, kumeBayt = 0;
for (let u = 1; u <= KULLANICI; u += 1) {
  sayacBayt += b(`hiz:${u}:2025073114`) + SAYI + EK_GIRIS;   // anahtarda pencere var
  let uye = b(`hiz:${u}`) + EK_GIRIS;
  for (let i = 0; i < SINIR; i += 1)               // her istek icin bir uye: zaman damgasi + sira
    uye += b(`1753963200000-${i}`) + SAYI + EK_DIZIN;
  kumeBayt += uye;
}
console.log(`hiz siniri (${KULLANICI} kullanici, dakikada ${SINIR} istek)`);
console.log(`  sayac       : tutulan=${sayacBayt} bayt  kullanici basina=${(sayacBayt / KULLANICI).toFixed(1)}` +
  `  giris=${KULLANICI}`);
console.log(`  sirali kume : tutulan=${kumeBayt} bayt  kullanici basina=${(kumeBayt / KULLANICI).toFixed(1)}` +
  `  giris=${KULLANICI * SINIR}  (${(kumeBayt / sayacBayt).toFixed(1)} kat)`);

// --- Senaryo 4: siralama tablosu. Ayni sayaclar; fark, sirali dizinin tutulup tutulmadigi.
function oduncSayilari(adet) {
  let tohum = 20250731;
  const rast = () => ((tohum = (tohum * 1103515245 + 12345) % 2147483648) / 2147483648);
  return Array.from({ length: adet }, (_, i) => [`Kitap ${i + 1}`, Math.floor(rast() * 900) + 1]);
}
const sayimlar = oduncSayilari(400);
let karmaBayt = b("populer") + EK_GIRIS, kumeSiraBayt = b("populer") + EK_GIRIS;
for (const [uye] of sayimlar) {
  karmaBayt += b(uye) + SAYI + EK_ALAN;            // yalniz ad ve sayi
  kumeSiraBayt += b(uye) + SAYI + EK_DIZIN;        // ustune sirali dizin dugumu
}

const sirali = [...sayimlar].sort((x, y) => y[1] - x[1] || (x[0] < y[0] ? -1 : 1));
let karmaDokunulan = 0, kumeDokunulan = 0;
const ilkOn = sirali.slice(0, 10);                 // kume: dizinin basindan on giris
kumeDokunulan += ilkOn.length;
karmaDokunulan += sayimlar.length;                 // karma: hepsi taranip siralanir

const hedefSkor = sayimlar[136][1];                // "Kitap 137" kacinci sirada
let karmaUstun = 0;                                // karmada yanit tam taramayla bulunur
for (const [, s] of sayimlar) if (s > hedefSkor) karmaUstun += 1;
karmaDokunulan += sayimlar.length;
let alt = 0, ust = sirali.length - 1, adim = 0;    // sirali dizinde ikili arama
while (alt <= ust) {
  const orta = (alt + ust) >> 1; adim += 1;
  if (sirali[orta][1] > hedefSkor) alt = orta + 1; else ust = orta - 1;
}
kumeDokunulan += adim;
console.log(`siralama tablosu (${sayimlar.length} kitap)`);
console.log(`  karma yapi  : tutulan=${karmaBayt} bayt  ilk on + sira icin dokunulan=${karmaDokunulan}`);
console.log(`  sirali kume : tutulan=${kumeSiraBayt} bayt  ilk on + sira icin dokunulan=${kumeDokunulan}` +
  `  (${(kumeSiraBayt / karmaBayt).toFixed(2)} kat bayt)`);
console.log(`  ilk uc: ${ilkOn.slice(0, 3).map(([a, s]) => `${a}=${s}`).join("  ")}`);
console.log(`  "Kitap 137" skoru=${hedefSkor}; daha yuksek skorlu kitap: karma=${karmaUstun}` +
  ` (400 giris) kume=${alt} (${adim} giris)`);
```

```
hiz siniri (2000 kullanici, dakikada 60 istek)
  sayac       : tutulan=84893 bayt  kullanici basina=42.4  giris=2000
  sirali kume : tutulan=5786893 bayt  kullanici basina=2893.4  giris=120000  (68.2 kat)
siralama tablosu (400 kitap)
  karma yapi  : tutulan=9915 bayt  ilk on + sira icin dokunulan=800
  sirali kume : tutulan=16315 bayt  ilk on + sira icin dokunulan=19  (1.65 kat bayt)
  ilk uc: Kitap 141=900  Kitap 211=900  Kitap 125=897
  "Kitap 137" skoru=533; daha yuksek skorlu kitap: karma=146 (400 giris) kume=146 (9 giris)
```

Hız sınırındaki fark altmış sekiz kattır ve nedeni tek cümleyle söylenebilir: sayaç kullanıcı
başına **bir** giriş tutar, sıralı küme **altmış** giriş tutar. Kullanıcı başına 42,4 bayt yerine
2.893,4 bayt ödenir. Karşılığında satın alınan şey, pencerenin içindeki her isteğin anının
bilinmesidir; sayaç bunu bilmez, yalnız kaç tane olduğunu bilir. Bu bilginin gerekli olup olmadığı
sınırın nasıl işleyeceğine bağlıdır ve o karar bu dersin dışındadır; ölçülen şey **fiyatıdır**.

Sıralama tablosunda oran çok daha küçüktür: 1,65 kat, yani 6.400 bayt. Karşılığı son iki satırda
görünür. İlk on kitabı ve bir kitabın sırasını bulmak karma yapıda 800 giriş dokunmayı gerektiriyor
(iki kez tam tarama), sıralı kümede 19 giriş yetiyor (on giriş baştan okunuyor, sıra dokuz adımlık
ikili aramayla bulunuyor). İki yol da aynı yanıtı veriyor: "Kitap 137"den daha çok ödünç verilen
146 kitap var.

Sıralı kümenin dizin payı bir kez ödenir ama her sorguda geri kazanılır. Katalog 400 değil 400.000
kitap olduğunda karma yapının tam taraması 800.000 girişe çıkarken sıralı kümenin işi 10 + 19
girişte kalır; fazladan ödenen bayt ise girişle doğru orantılı büyür.

## Dört Senaryo Tek Tabloda

| Senaryo | Yapı | Giriş | Tutulan bayt | Satın alınan | Kaybedilen |
|---|---|---|---|---|---|
| Katalog önbelleği | karma yapı | 400 | 60.623 | alan başına 8 baytlık yazma (dizgide 90 bayt) | dizgiye göre 14.508 bayt |
| Oturum kaydı | karma yapı + süre sonu | 750 canlı | 105.750 | belleğin oturum ömrüyle sınırlanması | süresi dolan oturumun verisi |
| Hız sınırı | sayaç | 2.000 | 84.893 | kullanıcı başına tek giriş | isteklerin tek tek anları |
| Sıralama tablosu | sıralı küme | 400 | 16.315 | ilk on ve sıra sorgusunda 19 giriş | karma yapıya göre 6.400 bayt |

Tablo dört ayrı iş gibi görünüyor ama tek bir karar biçimini tekrarlıyor. Her satırda yapı, o iş
için **hangi bilginin tutulması gerektiği** sorusuna verilen yanıttır. Bilgi ne kadar ayrıntılı
tutulursa erişim o kadar ucuzlar ve bellek o kadar pahalılaşır. Karma yapı alanları ayırdığı için
alan başına yazmayı, sıralı küme sırayı sakladığı için sıra sorgusunu ucuzlatır; sayaç ayrıntıyı
attığı için ucuzdur ve attığı ayrıntı geri gelmez.

## Özet

- Aynı kaydın dizgi biçimi 46.115, karma biçimi 60.623 bayt tuttu; karma yapının 14.508 baytlık
  fazlası, bin güncellemede 90.454 yerine 8.000 bayt yazmayla karşılandı.
- Oturum kaydında bellek kullanıcı sayısıyla değil oturum ömrüyle ölçeklenir: süre sonu 18.000
  oturumu 750 canlı oturuma indirdi, 2.538.000 bayt yerine 105.750 bayt.
- Hız sınırında sayaç kullanıcı başına 42,4 bayt, sıralı küme 2.893,4 bayt tutar; altmış sekiz
  katlık fark, tek tek istek anlarının saklanmasının fiyatıdır.
- Sıralama tablosunda sıralı kümenin dizin payı 6.400 bayttır ve ilk on ile sıra sorgusunu 800
  giriş yerine 19 girişe indirir; iki yol da aynı yanıtı verir.
- Dört senaryoda da yapı seçimi tek bir soruya bakar: hangi bilgi tutulacak. Ayrıntı tutuldukça
  erişim ucuzlar, bellek pahalılaşır.

## Sonraki Adım

Bu dersin bütün hesapları deponun **beklendiği gibi** çalıştığını varsaydı: her erişim sırası
geldiğinde yapılıyor, hiçbir istek bir başkasını beklemiyor. Bellek içi depoların çoğu komutları
tek bir iş parçacığında sırayla işler ve bu varsayım orada özel bir biçimde kırılır: 400.000
girişi tarayan tek bir komut, arkasında bekleyen bütün istekleri kendi süresi kadar geciktirir.
Sonraki ders bu gecikmeyi ölçer, bekleyen istek sayısını sayar ve yavaş komut günlüğünün eşiğini
tarayarak sorunlu komutun nasıl görünür kılındığını gösterir.
