---
title: 'Yanında Okuma'
source: 'https://academia.sh/tr/kurslar/veri-olcekleme/yaninda-okuma'
course: 'Veri Katmanı Ölçekleme'
language: tr
updated: '2026-08-17T18:11:01+00:00'
license: 'CC BY-SA 4.0'
---

# Yanında Okuma

Uygulama denetimli önbelleğin ölçekleme aracı olarak ele alınması: isabet oranının yazma/okuma oranının bir işlevi hâline getirilmesi, giriş kursunun 0,2333'lük oranında 0,90 varsayımının 0,7287'ye düşmesi, her geçersizleştirmenin bir depo okuması doğurması ve önbellek katmanı kısmen bozulduğunda uygulamanın depoya kendi gidebilmesinin ölçülmesi.

Önceki ders dört katmanı bir zincir olarak ölçtü ve hepsi aynı biçimde davrandı: bak, yoksa bir
alttakine sor, dönüşte koy. O davranışın adı **yanında okuma** (cache-aside) ve önbellek
katmanının isabeti yalnız kapasiteye bağlı değil; girdiyi düşüren ikinci bir kuvvet var ve o
kuvvet yazmadır. Kabaca büyüklük hesabı deponun gördüğü yerde yazma ağırlıklı bir sistem tarif
ediyordu: `depoda yazma/okuma orani` 2,33. Bu ders isabet oranını sabit bir sayı olmaktan
çıkarıp yazma sıklığının bir işlevi hâline getirir.

Yanında okumanın mekaniği Önbellekleme, Kuyruklar ve Eşzamansız İşleme kursunda kuruldu ve
ölçüldü; burada yeniden anlatılmaz. Buradaki iki soru başkadır: bu strateji hangi katmana ait
ve K01'in yazma hızında ne veriyor.

## Uygulama Denetimli Olmak Ne Demek

Yanında okumanın tanımlayıcı özelliği, önbelleğin okuma yolunun **yanında** durmasıdır: veriyi
getirme sorumluluğu önbellekte değil, uygulamadadır. Aynı okuma yolunun iki gerçekleştirimi
vardır — uygulama kodunun elle baktığı biçim ve okumanın önbellek katmanının üzerinden geçtiği
biçim — ve ikisi de bu adla anılır. Fark mekanikte değil, sorumluluğun nerede durduğundadır ve
son bölümde ölçülen tek şey odur.

Bu strateji, önbelleğin **yazma yoluna bağlanamadığı** her yerde tek seçenektir. Gönderi takip
servisinde durum olayları uygulama katmanının okuma yolundan gelmez: taşıyıcıdan gelir, Uygulama
Katmanı ve Servis Etkileşimi kursunda tasarlanan kuyruk üzerinden işlenir ve depoya oradan
yazılır. Okuma yolundaki önbellek o yazmanın olduğu yerde değildir; yazıldığını ancak bir
geçersizleştirme iletisiyle öğrenir. Bu yüzden okuma yolu önbelleğinin yapabileceği tek şey
girdiyi **silmek**tir, güncellemek değil. Yazmanın önbelleğe bağlanabildiği durum sonraki dersin
konusudur.

Katman seçimi de buradan çıkar. Önceki dersin ölçümünde uygulama katmanındaki paylaşılan
önbellek isabetin yalnız küçük bir payını durduruyordu, ama geri alınabilirliği en yüksek katman
oydu: bir silme iletisi ancak orada anında uygulanabilir. Yanında okuma bu yüzden uygulama
katmanına konur; kenar ve istemci katmanları aynı stratejiyi çalıştıramaz çünkü onlarda silme
yoktur, yalnız süre vardır.

## Yazmanın İsabete Etkisi

Model süreç içidir ve tek katmanlıdır: önceki dersin ölçümü kapasitesi 2000 olan tek bir
paylaşılan önbelleğin çalışma kümesini karşıladığını gösterdiği için burada kapasite bağlayıcı
kısıt olmaktan çıkarılır ve tek değişken yazma oranı olur.

**B1 (bu dersin varsayımı): durum olayları, o anda sorgulanan gönderilere düşer.** Gerekçe: bir
gönderi tam da yolda olduğu için hem olay üretir hem sorgulanır. Bu, geçersizleştirmenin en güçlü
olduğu yöndür; duyarlılık: olayların yarısı sorgulanmayan gönderilere düşerse silme sayısı ve
doğurduğu ek okuma yarıya iner. Varsayım K01'in tablosuna eklenmez.

```js
// onbellek/yaninda.mjs — yaninda okumanin surec ici modeli. Onbellek, depo ve olay akisi
// birer modul; sayaclar aciktir. Yazma/okuma orani, kapasite ve ariza payi parametredir.
export function kutuAc(kapasite) {
  const m = new Map();
  const o = {
    tahliye: 0,
    var: (a) => m.has(a),
    al(a) { const d = m.get(a); if (d !== undefined) { m.delete(a); m.set(a, d); } return d; },
    koy(a, d) { m.delete(a); m.set(a, d); if (m.size > kapasite) { m.delete(m.keys().next().value); o.tahliye += 1; } },
    sil: (a) => m.delete(a),
  };
  return o;
}

// Akis: okuma ve yazma ayni etkin gonderi kumesine duser (B1). `oran` yazma/okuma oranidir.
export function akis({ okuma, oran, calismaKumesi, obek }) {
  let tohum = 20260730;
  const rast = () => ((tohum = (tohum * 1103515245 + 12345) % 2147483648) / 2147483648);
  let sonraki = 1;
  const etkin = Array.from({ length: calismaKumesi }, () => ({ no: sonraki++, kalan: obek }));
  const cikti = [];
  let borc = 0;
  for (let i = 0; i < okuma; i++) {
    const j = Math.floor(rast() * etkin.length);
    const g = etkin[j];
    cikti.push(["oku", `takip:${g.no}`]);
    if ((g.kalan -= 1) === 0) etkin[j] = { no: sonraki++, kalan: obek };
    for (borc += oran; borc >= 1; borc -= 1)
      cikti.push(["yaz", `takip:${etkin[Math.floor(rast() * etkin.length)].no}`]);
  }
  return cikti;
}

// Yaninda okuma: okumada bak-getir-koy, yazmada depoya yaz ve girdiyi sil.
// gecersizlestir=false: yazma girdiyi silmez. ariza: onbellek isleminin basarisiz olma payi.
// atlayabilir=false: okuma onbellegin uzerinden gecer, uygulama depoya kendi gidemez.
export function kosum(islemler, { kapasite, gecersizlestir = true, ariza = 0, atlayabilir = true }) {
  const c = kutuAc(kapasite);
  let tohum = 991;
  const bozuk = () => ariza > 0 && ((tohum = (tohum * 1103515245 + 12345) % 2147483648) / 2147483648) < ariza;
  const s = { isabet: 0, iska: 0, depoOkuma: 0, depoYazma: 0, silme: 0, bayat: 0, dokunus: 0, karsilanmayan: 0 };
  const dogru = new Map();
  let surum = 0;
  for (const [tur, anahtar] of islemler) {
    if (!dogru.has(anahtar)) dogru.set(anahtar, 0);
    if (tur === "oku") {
      s.dokunus += 1;
      if (bozuk()) {
        if (!atlayabilir) { s.karsilanmayan += 1; continue; }
        s.iska += 1; s.depoOkuma += 1; s.dokunus += 1;
        continue;
      }
      if (c.var(anahtar)) {
        s.isabet += 1;
        if (c.al(anahtar) !== dogru.get(anahtar)) s.bayat += 1;
        continue;
      }
      s.iska += 1; s.depoOkuma += 1; s.dokunus += 2;
      c.koy(anahtar, dogru.get(anahtar));
    } else {
      dogru.set(anahtar, (surum += 1));
      s.depoYazma += 1; s.dokunus += 1;
      if (!gecersizlestir) continue;
      s.dokunus += 1;
      if (bozuk()) continue;                       // silme kaybolur: girdi bayat kalir
      if (c.sil(anahtar)) s.silme += 1;
    }
  }
  return { ...s, tahliye: c.tahliye };
}

// M19/K01 kabaca buyukluk hesabinin girdileri (V1-V4, V8).
export const K01 = {
  tepeOkuma: (2_000_000 * 6 / 86_400) * 3,
  tepeYazma: (400_000 * 7 / 86_400) * 3,
};
```

```js
// onbellek/oran.mjs — isabet oraninin yazma/okuma oraninin islevi olarak olculmesi
import { akis, kosum, K01 } from "./yaninda.mjs";

const OKUMA = 200_000, KAPASITE = 2000, CALISMA = 1000, OBEK = 10;
const K01_ORAN = K01.tepeYazma / K01.tepeOkuma;

console.log(`okuma ${OKUMA}, kapasite ${KAPASITE}, es zamanli gonderi ${CALISMA}, obek ${OBEK}`);
console.log(`K01 yazma/okuma orani = ${K01_ORAN.toFixed(4)} (tepe yazma ${K01.tepeYazma.toFixed(2)} / tepe okuma ${K01.tepeOkuma.toFixed(2)})`);
console.log();
console.log("yazma/okuma   yazma   isabet  depo okuma  onbellek arkasi/s  depoya ulasan/s  depoda yazma/okuma");
console.log("----------- ------- -------- ----------- ------------------ ---------------- ------------------");
for (const oran of [0, 0.05, 0.1167, K01_ORAN, 0.4667, 1]) {
  const islemler = akis({ okuma: OKUMA, oran, calismaKumesi: CALISMA, obek: OBEK });
  const r = kosum(islemler, { kapasite: KAPASITE });
  const h = r.isabet / OKUMA;
  const arka = K01.tepeOkuma * (1 - h);
  const etiket = Math.abs(oran - K01_ORAN) < 1e-9 ? `${oran.toFixed(4)}*` : oran.toFixed(4);
  console.log(`${etiket.padStart(11)} ${String(r.depoYazma).padStart(7)} ${h.toFixed(4).padStart(8)} ` +
    `${String(r.depoOkuma).padStart(11)} ${arka.toFixed(2).padStart(18)} ` +
    `${(arka + K01.tepeYazma).toFixed(2).padStart(16)} ${(K01.tepeYazma / arka).toFixed(2).padStart(18)}`);
}
console.log("* K01'in tepe hizlarindan cikan oran");

console.log();
const islemler = akis({ okuma: OKUMA, oran: K01_ORAN, calismaKumesi: CALISMA, obek: OBEK });
const ile = kosum(islemler, { kapasite: KAPASITE });
const olmadan = kosum(islemler, { kapasite: KAPASITE, gecersizlestir: false });
console.log(`K01 oraninda gecersizlestirme ile   : isabet ${(ile.isabet / OKUMA).toFixed(4)}  depo okuma ${ile.depoOkuma}  silme ${ile.silme}  bayat okuma ${ile.bayat}`);
console.log(`K01 oraninda gecersizlestirme olmadan: isabet ${(olmadan.isabet / OKUMA).toFixed(4)}  depo okuma ${olmadan.depoOkuma}  silme ${olmadan.silme}  bayat okuma ${olmadan.bayat}`);
console.log(`silme basina dogan ek depo okumasi  = ${((ile.depoOkuma - olmadan.depoOkuma) / ile.silme).toFixed(2)}`);
console.log(`yazma basina ek islem               = ${((ile.dokunus - olmadan.dokunus) / ile.depoYazma).toFixed(2)} dokunus + ${((ile.depoOkuma - olmadan.depoOkuma) / ile.depoYazma).toFixed(2)} depo okumasi`);
```

```
okuma 200000, kapasite 2000, es zamanli gonderi 1000, obek 10
K01 yazma/okuma orani = 0.2333 (tepe yazma 97.22 / tepe okuma 416.67)

yazma/okuma   yazma   isabet  depo okuma  onbellek arkasi/s  depoya ulasan/s  depoda yazma/okuma
----------- ------- -------- ----------- ------------------ ---------------- ------------------
     0.0000       0   0.8976       20483              42.67           139.90               2.28
     0.0500   10000   0.8551       28976              60.37           157.59               1.61
     0.1167   23340   0.8039       39212              81.69           178.91               1.19
    0.2333*   46666   0.7287       54257             113.04           210.26               0.86
     0.4667   93340   0.6134       77312             161.07           258.29               0.60
     1.0000  200000   0.4523      109549             228.23           325.45               0.43
* K01'in tepe hizlarindan cikan oran

K01 oraninda gecersizlestirme ile   : isabet 0.7287  depo okuma 54257  silme 33957  bayat okuma 0
K01 oraninda gecersizlestirme olmadan: isabet 0.8977  depo okuma 20451  silme 0  bayat okuma 105794
silme basina dogan ek depo okumasi  = 1.00
yazma basina ek islem               = 2.45 dokunus + 0.72 depo okumasi
```

Bütün sayılar **hesap** sınıfındadır; belirlenimli bir akış üzerinde sayılmışlardır ve süre
ölçülmemiştir.

Birinci satır yazma yokken önceki dersin sonucunu tekrarlıyor: isabet 0,8976, `depoya ulasan
istek/s` 139,90. K01'in varsayımı burada tutuyor. K01'in kendi yazma hızında ise tutmuyor.
Yazma/okuma oranı 0,2333 olduğunda isabet **0,7287**'ye düşüyor, `onbellek arkasi okuma/s`
41,67'den 113,04'e, `depoya ulasan istek/s` 138,89'dan **210,26**'ya çıkıyor. V9 = 0,90
varsayımı örtük olarak "önbelleğe hiç yazılmıyor" demekti; sistem kendi yazma hızını
gördüğünde varsayım yüzde on dokuz eksiliyor.

`depoda yazma/okuma orani` sütunu daha da ilginç. K01 bu oranı 2,33 hesaplamış ve "okuma
ağırlıklı diye tarif edilen sistem, deponun gördüğü yerde yazma ağırlıklıdır" demişti. Yanında
okumanın gerçek isabetiyle oran **0,86**'ya iniyor: geçersizleştirme deponun okuma yükünü öyle
büyütüyor ki depo yeniden okuma ağırlıklı hâle geliyor. Yazma sayısı hiç değişmedi; değişen,
her yazmanın doğurduğu okumadır.

Son üç satır o doğurmayı sayıyor. K01 oranında 33.957 girdi silindi ve depo okuması 20.451'den
54.257'ye çıktı: **silme başına 1,00 ek depo okuması**. Silinen girdi neredeyse her zaman yeniden
okunuyor, çünkü silinme nedeni tam da o gönderinin etkin olmasıdır. Bir yazmanın önbelleğe
maliyeti böylece "bir silme" değil, "bir silme artı 0,72 depo okuması"dır.

Geçersizleştirme kapatıldığında isabet 0,8977'ye geri dönüyor ve fatura başka bir sütunda
görünüyor: 105.794 bayat okuma, yani okumaların yarıdan fazlası. Yanında okumanın ödünleşimi bu
iki sütun arasındadır ve ikisinin ortasındaki bölge — kabul edilebilir bayatlık penceresi — bu
konunun son dersinin konusudur.

## Uygulamanın Depoya Kendi Gidebilmesi

İki gerçekleştirim biçimi arasındaki fark, önbellek katmanı bozulduğunda ölçülebilir hâle gelir.
Model, önbellek işlemlerinin bir payını başarısız kılar; uygulama denetimli biçim bunu ıska
sayıp depoya gider, üzerinden geçen biçim ise isteği karşılayamaz.

```js
// onbellek/ariza.mjs — onbellek katmani kismen bozuldugunda iki bicimin davranisi
import { akis, kosum, K01 } from "./yaninda.mjs";

const OKUMA = 200_000, KAPASITE = 2000;
const ORAN = K01.tepeYazma / K01.tepeOkuma;
const islemler = akis({ okuma: OKUMA, oran: ORAN, calismaKumesi: 1000, obek: 10 });

console.log("ariza  bicim               karsilanan  isabet  depo okuma  depoya ulasan/s  bayat okuma");
console.log("------ ------------------- ---------- ------- ----------- ---------------- -----------");
for (const ariza of [0, 0.1, 0.5, 1]) {
  for (const [ad, atlayabilir] of [["uygulama denetimli", true], ["uzerinden gecen", false]]) {
    const r = kosum(islemler, { kapasite: KAPASITE, ariza, atlayabilir });
    const karsilanan = OKUMA - r.karsilanmayan;
    const h = r.isabet / OKUMA;
    const depoS = K01.tepeOkuma * (r.depoOkuma / OKUMA) + K01.tepeYazma;
    console.log(`${ariza.toFixed(2).padStart(6)} ${ad.padEnd(19)} ${(karsilanan / OKUMA).toFixed(4).padStart(10)} ` +
      `${h.toFixed(4).padStart(7)} ${String(r.depoOkuma).padStart(11)} ${depoS.toFixed(2).padStart(16)} ${String(r.bayat).padStart(11)}`);
  }
}
```

```
ariza  bicim               karsilanan  isabet  depo okuma  depoya ulasan/s  bayat okuma
------ ------------------- ---------- ------- ----------- ---------------- -----------
  0.00 uygulama denetimli      1.0000  0.7287       54257           210.26           0
  0.00 uzerinden gecen         1.0000  0.7287       54257           210.26           0
  0.10 uygulama denetimli      1.0000  0.6468       70650           244.41        7473
  0.10 uzerinden gecen         0.8974  0.6468       50126           201.65        7473
  0.50 uygulama denetimli      1.0000  0.3209      135818           380.18       18780
  0.50 uzerinden gecen         0.4876  0.3209       33334           166.67       18780
  1.00 uygulama denetimli      1.0000  0.0000      200000           513.89           0
  1.00 uzerinden gecen         0.0000  0.0000           0            97.22           0
```

Sağlıklı durumda iki biçim aynı satırı üretiyor; fark yalnız arıza altında var. Önbellek
tamamen çöktüğünde uygulama denetimli biçim isteklerin tamamını karşılamayı sürdürüyor ve depoya
ulaşan istek 513,89 istek/s'ye çıkıyor — K01'in uçtaki tepe yükünün tamamı. Bu sayı bir tasarım
şartıdır: yanında okumayı seçmek, deponun bu yükü kısa süre taşıyabilmesini şart koşar. Üzerinden
geçen biçimde ise karşılanan istek oranı sıfıra iniyor; servisin hizmet erişilebilirliği
önbellek katmanının ayakta kalmasına bağlanmış olur.

Depoya ulaşan istek sütunu bu satırlarda yanıltıcıdır ve bilerek yan yana konmuştur: yüzde elli
arızada üzerinden geçen biçimin deposu 166,67 istek/s ile sağlıklı durumdakinden **daha az** yük
görüyor. Depo yükü düşük görünürken isteklerin yarısı hiç yanıtlanmıyor. Bir ölçütün iyileşmesi
tek başına okunamaz.

Üçüncü sütun beklenmedik bir sonucu taşıyor: yüzde on arızada 7473 bayat okuma var, oysa sağlıklı
koşumda hiç yoktu. Kaybolan şey okumalar değil **silmelerdir**; başarısız bir silme, hiçbir
sayaçta hata olarak görünmeden bayat bir girdi bırakır. Yanında okumanın doğruluğu, en gürültüsüz
biçimde başarısız olan işleme bağlıdır.

## Özet

- Yanında okuma, veriyi getirme sorumluluğunun önbellekte değil uygulamada olduğu okuma yolu
  önbelleğidir; yazmanın önbelleğe bağlanamadığı yerde tek seçenektir ve yapabildiği tek şey
  girdiyi silmektir.
- İsabet oranı yazma/okuma oranının işlevidir: yazma yokken 0,8976, K01'in 0,2333'lük oranında
  **0,7287**. V9 = 0,90 varsayımı örtük olarak yazmasız bir sistem varsayıyordu.
- K01'e dönüş: `onbellek arkasi okuma/s` 41,67'den 113,04'e, `depoya ulasan istek/s` 138,89'dan
  210,26'ya çıkıyor; `depoda yazma/okuma orani` 2,33'ten 0,86'ya iniyor, yani depo yeniden okuma
  ağırlıklı hâle geliyor.
- Silme başına 1,00 ek depo okuması doğuyor; bir yazmanın önbelleğe maliyeti 2,45 dokunuş ve 0,72
  depo okumasıdır. Geçersizleştirme kapatılırsa isabet 0,8977'ye döner ama 105.794 bayat okuma
  oluşur.
- Önbellek tamamen çöktüğünde uygulama denetimli biçim isteklerin tamamını karşılar ve depoya
  513,89 istek/s biner; üzerinden geçen biçimde karşılanan istek sıfırlanır. Kısmi arızada
  kaybolan silmeler 7473 bayat okuma bırakır.

## Sonraki Adım

Bu dersin bütün maliyeti tek bir kısıttan doğdu: önbellek yazmanın olduğu yerde değildi, bu
yüzden yeni değeri koyamadı, yalnız eskisini sildi ve her silme bir depo okuması doğurdu. Kısıt
her zaman geçerli değildir. Gönderi durumunu depoya yazan yol uygulamanın kendi içinden geçiyorsa
önbelleğe yeni değer yazmanın önünde bir engel kalmaz; yazma iki yere birden gider ve silme
hiç yapılmaz. Aynı bağ bir adım daha ileri götürülüp yazma önce önbelleğe, depoya sonra
toplu olarak da gönderilebilir — bu kez değişen sayı okuma tarafında değil, `depoda yazma/okuma
orani` satırının payındadır. Sonraki ders yazma yolunun önbelleğe bağlandığı bu iki düzeni
ölçer: yazma yolunun kaç yere uzadığını, yazma başına ne kadar ek iş çıktığını ve süreç
durduğunda kaç olayın bellekte kaldığını.
