İçeriğe geç
academia.sh

Ders 11 / 30

Depolama ve Birimler

Kalıcı birim talebi ile küme arzının eşlenmesi: uygulamanın bildirdiği boyut, erişim kipi ve başarım sınıfı karşısında kümenin sunduğu birim havuzu, karşılanamayan taleplerin nedene göre sayımı, bağlama kipinin yerleştirmeden elediği düğüm sayısı ve envanter bildirimi eskidiğinde ortaya çıkan yanlış bağlama.

İçindekiler

Ayarlar kapsülün dışına çıktı: yapılandırma ve sır ayrı nesneler olarak duruyor, kapsül onları koşum anında okuyor. Veri için aynı şey söylenemez. Kapsülün yazdığı her bayt hâlâ kapsülün ömrüne bağlı; kapsül yeniden yaratıldığında yeni bir yazılabilir katmanla başlıyor ve dünkü iş durumu orada değil.

Tek makinede bu sorunun çözümü ölçülmüştü — veriyi yazılabilir katmanın dışına, adla anılan bir birime ya da mutlak yolla anılan bir dizine çıkarmak — ve orada sayılan şey konteyner silindikten sonra kalan bayttı. Kümede o sayı çözülmüş kabul edilir; sorulan soru başkadır. Kapsül hangi düğümde açılırsa açılsın aynı baytları bulacaksa, o baytları tutan depolamanın o düğümden erişilebilir olması gerekir. Bu, uygulamanın tek başına veremeyeceği bir karardır: uygulama ne istediğini bilir, kümenin ne sunduğunu bilmez.

Devir burada ikiye bölünmüş bir bildirimle yapılır. Uygulama bir kalıcı birim talebi yazar; küme bir birim havuzu bildirir; ikisini eşleyen şey bir depolama sürücü arayüzüdür. Bu ders üç şeyi sayıyor: kaç talep karşılanamıyor ve neden, bağlama kipi yerleştirmeden kaç seçenek eliyor, envanter bildirimi eskidiğinde kaç bağlama yanlış çıkıyor.

Talep, Arz ve Eşleme

Talep ve arz aynı sözlüğü kullanmak zorundadır. Uygulama üç kalem bildirir: ne kadar yer, hangi erişim kipi, hangi başarım sınıfı. Küme her birim için dört kalem bildirir: boyut, sınıf, desteklediği kipler ve topoloji. Eşleme kuralı üç karşılaştırmadan ibarettir; zor olan karşılaştırma değil, iki tarafın da güncel bildirim yapmasıdır.

  • TN31 — Küme, birim havuzu, düğüm topolojisi ve envanter bildirimi node içinde kurulan bir modeldir; gerçek bir küme koşturulmuyor. Aşağıdaki sayılar modelin sayılarıdır.
  • TN32 — Ölçüm ağı kurgudur. On kalıcı birim talebi ağın servislerinden ve gecelik toplu işinden geliyor; adlar o kurgudan alınmıştır.
  • TN33 — Başarım sınıfları hizli, standart, arsiv ve cok-hizli; erişim kipleri tek düğüm yazar, çok düğüm okur, çok düğüm yazar.
  • TN34 — Küme altı düğüm ve iki bölgedir. Bir birim ya tek bir düğüme bağlıdır ya da bir bölgenin tamamına açıktır; üçüncü topoloji yok.
  • TN35 — Eskime taramasında havuz 24 birim, koşum 10 tur, tur başına dört talep gelir. Her tur iki birim küme dışındaki başka bir istekçiye bağlanır, bir birim serbest kalır.
  • TN36 — Rastgelelik doğrusal eşlenik üreteçle üretiliyor, tohum 20260801. Üç envanter yaşı aynı havuz ve aynı talep dizisiyle koşuyor.
// olcum/talep-arz.mjs — kalici birim talebi ile kume arzinin eslenmesi ve yerlestirme kisiti.
// MODEL: kume, birim havuzu, dugum topolojisi ve envanter bildirimi node icinde kurulan modeldir;
// gercek bir kume kosturulmuyor. Sayilar modelin sayilaridir.
const DUGUM = [["d1", "bolge-a"], ["d2", "bolge-a"], ["d3", "bolge-a"],
  ["d4", "bolge-b"], ["d5", "bolge-b"], ["d6", "bolge-b"]];

// talep: ad, boyut(Gi), erisim kipi, basarim sinifi  -> uygulamanin bildirdigi 3 kalem
const TALEP = [
  ["toplayici-durum", 20, "tek-yazar", "hizli"], ["dogrulayici-onbellek", 5, "tek-yazar", "standart"],
  ["faturalama-veri", 200, "tek-yazar", "hizli"], ["is-emri-veri", 50, "tek-yazar", "standart"],
  ["tarife-tablosu", 2, "cok-okur", "standart"], ["gecelik-cikti", 100, "cok-yazar", "standart"],
  ["arsiv-2025", 500, "cok-okur", "arsiv"], ["olcum-ham", 300, "tek-yazar", "hizli"],
  ["rapor-paylasim", 40, "cok-yazar", "hizli"], ["kapanis-defteri", 30, "tek-yazar", "cok-hizli"]];

// arz: ad, boyut(Gi), sinif, desteklenen kipler, bolge, bagli dugum (yoksa bolge geneli)
const ARZ = [
  ["b01", 30, "hizli", ["tek-yazar"], "bolge-a", "d1"], ["b02", 8, "standart", ["tek-yazar"], "bolge-a", "d2"],
  ["b03", 250, "hizli", ["tek-yazar"], "bolge-b", "d4"], ["b04", 60, "standart", ["tek-yazar"], "bolge-b", "d5"],
  ["b05", 4, "standart", ["tek-yazar", "cok-okur"], "bolge-a", null],
  ["b06", 120, "standart", ["tek-yazar"], "bolge-a", null], ["b07", 400, "arsiv", ["tek-yazar", "cok-okur"], "bolge-b", null],
  ["b08", 20, "hizli", ["tek-yazar"], "bolge-a", "d3"], ["b09", 512, "standart", ["tek-yazar", "cok-okur"], "bolge-b", null],
  ["b10", 50, "hizli", ["tek-yazar", "cok-okur", "cok-yazar"], "bolge-a", null]];

const uyar = (t, b) => b[1] >= t[1] && b[2] === t[3] && b[3].includes(t[2]);
function esle(kural) {                                        // kural: ilk-uyan | en-kucuk-uyan
  const bos = new Set(ARZ.map((b) => b[0])), sonuc = [];
  for (const t of TALEP) {
    const aday = ARZ.filter((b) => bos.has(b[0]) && uyar(t, b));
    if (aday.length) {
      const s = kural === "ilk-uyan" ? aday[0] : aday.reduce((a, b) => (b[1] < a[1] ? b : a));
      bos.delete(s[0]); sonuc.push([t, s, null]); continue;
    }
    const sinif = ARZ.some((b) => bos.has(b[0]) && b[2] === t[3]);
    const kip = ARZ.some((b) => bos.has(b[0]) && b[2] === t[3] && b[3].includes(t[2]));
    sonuc.push([t, null, !sinif ? "sinif yok" : !kip ? "kip yok" : "boyut yetmiyor"]);
  }
  return sonuc;
}

const A = esle("en-kucuk-uyan"), neden = {};
console.log(`${"talep".padEnd(22)}${"Gi".padStart(5)}${"kip".padStart(11)}${"sinif".padStart(10)}${"birim".padStart(7)}${"sonuc".padStart(16)}`);
for (const [t, b, n] of A) {
  if (n) neden[n] = (neden[n] || 0) + 1;
  console.log(`${t[0].padEnd(22)}${String(t[1]).padStart(5)}${t[2].padStart(11)}${t[3].padStart(10)}` +
    `${(b ? b[0] : "-").padStart(7)}${(b ? "baglandi" : n).padStart(16)}`);
}
const bagli = A.filter(([, b]) => b);
console.log(`${TALEP.length} talebin ${bagli.length} tanesi karsilandi, ${TALEP.length - bagli.length} tanesi karsilanmadi: ` +
  Object.entries(neden).map(([k, v]) => `${k} ${v}`).join(", "));
for (const k of ["ilk-uyan", "en-kucuk-uyan"]) {
  const r = esle(k).filter(([, b]) => b);
  console.log(`kural ${k.padEnd(15)} karsilanan ${r.length}  fazla ayrilan ${r.reduce((a, [t, b]) => a + b[1] - t[1], 0)} Gi`);
}

const uygunlar = (b) => DUGUM.filter(([d, bo]) => (b[5] ? d === b[5] : bo === b[4])).map(([d]) => d);
console.log(`\n${"talep".padEnd(22)}${"kip".padStart(11)}${"birim topolojisi".padStart(20)}${"uygun dugum".padStart(13)}${"elenen".padStart(8)}`);
let uygunTop = 0;
for (const [t, b] of bagli) {
  const u = uygunlar(b); uygunTop += u.length;
  console.log(`${t[0].padEnd(22)}${t[2].padStart(11)}${(b[5] ? `dugum ${b[5]}` : `bolge ${b[4]}`).padStart(20)}` +
    `${u.join(",").padStart(13)}${String(DUGUM.length - u.length).padStart(8)}`);
}
console.log(`kisitsiz ${bagli.length * DUGUM.length} yerlestirme secenegi vardi, ${uygunTop} tanesi kaldi; elenen ${bagli.length * DUGUM.length - uygunTop}`);
for (const k of ["tek-yazar", "cok-okur", "cok-yazar"]) {
  const g = bagli.filter(([t]) => t[2] === k); if (!g.length) continue;
  console.log(`kip ${k.padEnd(10)} talep ${g.length}  talep basina ortalama uygun dugum ` +
    `${(g.reduce((a, [, b]) => a + uygunlar(b).length, 0) / g.length).toFixed(2)}`);
}

// --- envanter eskimesi: karar eski bildirimle veriliyor ---
const TOHUM = 20260801;
let s = TOHUM % 2147483647;
const rast = () => (s = (s * 48271) % 2147483647) / 2147483647;
const HAVUZ = 24, TUR = 10, TUR_TALEP = 4, DIS = 2;
const havuz = Array.from({ length: HAVUZ }, (_, i) => [`h${String(i + 1).padStart(2, "0")}`,
  [10, 40, 120, 400][Math.floor(rast() * 4)], ["hizli", "standart", "arsiv"][Math.floor(rast() * 3)]]);
const gelen = [];
for (let t = 0; t < TUR; t += 1)
  for (let i = 0; i < TUR_TALEP; i += 1)
    gelen.push([t, [10, 40, 120][Math.floor(rast() * 3)], ["hizli", "standart", "arsiv"][Math.floor(rast() * 3)]]);

function kosum(yas) {
  s = TOHUM % 2147483647; for (let i = 0; i < 3 * HAVUZ + 2 * gelen.length; i += 1) rast();
  const dolu = new Set(), gecmis = [], kuyruk = [];
  let dogru = 0, yanlis = 0, kararsiz = 0, bekleme = 0;
  for (let t = 0; t < TUR; t += 1) {
    gecmis.push(new Set(dolu));
    const envanter = yas === 0 ? dolu : gecmis[Math.max(0, t - yas)];
    kuyruk.push(...gelen.filter((g) => g[0] === t));
    for (const talep of kuyruk.splice(0, kuyruk.length)) {
      const aday = havuz.find((b) => !envanter.has(b[0]) && b[1] >= talep[1] && b[2] === talep[2]);
      if (!aday) { kararsiz += 1; kuyruk.push(talep); continue; }
      if (dolu.has(aday[0])) { yanlis += 1; kuyruk.push(talep); continue; }
      dolu.add(aday[0]); dogru += 1; bekleme += t - talep[0];
    }
    for (let i = 0; i < DIS; i += 1) {                        // baska bir istekci havuzdan birim baglar
      const bos = havuz.filter((b) => !dolu.has(b[0]));
      if (bos.length) dolu.add(bos[Math.floor(rast() * bos.length)][0]);
    }
    const d = [...dolu]; if (d.length) dolu.delete(d[Math.floor(rast() * d.length)]);
  }
  return { dogru, yanlis, kararsiz, bekleme, bekleyen: kuyruk.length };
}

console.log(`\n${"envanter yasi"}${"dogru".padStart(8)}${"yanlis baglama".padStart(16)}${"karar verememe".padStart(16)}` +
  `${"bekleyen".padStart(10)}${"ort. bekleme turu".padStart(19)}${"tur basina bildirim".padStart(21)}`);
for (const yas of [0, 1, 3]) {
  const r = kosum(yas);
  console.log(`${String(yas).padEnd(13)}${String(r.dogru).padStart(8)}${String(r.yanlis).padStart(16)}` +
    `${String(r.kararsiz).padStart(16)}${String(r.bekleyen).padStart(10)}${(r.bekleme / Math.max(1, r.dogru)).toFixed(2).padStart(19)}` +
    `${String(Math.round(HAVUZ * 3 / (yas + 1))).padStart(21)}`);
}
console.log(`bilgi kalemi: ${TALEP.length} talep x 3 + ${ARZ.length} birim x 4 + ${DUGUM.length} dugum x 1 = ` +
  `${TALEP.length * 3 + ARZ.length * 4 + DUGUM.length} kalem (tohum ${TOHUM})`);
talep                    Gi        kip     sinif  birim           sonuc
toplayici-durum          20  tek-yazar     hizli    b08        baglandi
dogrulayici-onbellek      5  tek-yazar  standart    b02        baglandi
faturalama-veri         200  tek-yazar     hizli    b03        baglandi
is-emri-veri             50  tek-yazar  standart    b04        baglandi
tarife-tablosu            2   cok-okur  standart    b05        baglandi
gecelik-cikti           100  cok-yazar  standart      -         kip yok
arsiv-2025              500   cok-okur     arsiv      -  boyut yetmiyor
olcum-ham               300  tek-yazar     hizli      -  boyut yetmiyor
rapor-paylasim           40  cok-yazar     hizli    b10        baglandi
kapanis-defteri          30  tek-yazar cok-hizli      -       sinif yok
10 talebin 6 tanesi karsilandi, 4 tanesi karsilanmadi: kip yok 1, boyut yetmiyor 2, sinif yok 1
kural ilk-uyan        karsilanan 6  fazla ayrilan 85 Gi
kural en-kucuk-uyan   karsilanan 6  fazla ayrilan 75 Gi

talep                         kip    birim topolojisi  uygun dugum  elenen
toplayici-durum         tek-yazar            dugum d3           d3       5
dogrulayici-onbellek    tek-yazar            dugum d2           d2       5
faturalama-veri         tek-yazar            dugum d4           d4       5
is-emri-veri            tek-yazar            dugum d5           d5       5
tarife-tablosu           cok-okur       bolge bolge-a     d1,d2,d3       3
rapor-paylasim          cok-yazar       bolge bolge-a     d1,d2,d3       3
kisitsiz 36 yerlestirme secenegi vardi, 10 tanesi kaldi; elenen 26
kip tek-yazar  talep 4  talep basina ortalama uygun dugum 1.00
kip cok-okur   talep 1  talep basina ortalama uygun dugum 3.00
kip cok-yazar  talep 1  talep basina ortalama uygun dugum 3.00

envanter yasi   dogru  yanlis baglama  karar verememe  bekleyen  ort. bekleme turu  tur basina bildirim
0                  21               0              80        19               0.33                   72
1                  15              86              44        25               1.93                   36
3                  10             134              33        30               3.20                   18
bilgi kalemi: 10 talep x 3 + 10 birim x 4 + 6 dugum x 1 = 76 kalem (tohum 20260801)

Karşılanamayan Talep: Dört Ret, Üç Neden

On talebin altısı bağlandı, dördü karşılanmadı ve ret nedenleri aynı sınıfta değil. Bir talep kip yok dedi: gecelik toplu işin çıktısı için çok düğüm yazar kipinde bir birim isteniyor, havuzda o boyutta ve o sınıfta birim var ama hiçbiri o kipi desteklemiyor. İki talep boyut yetmiyor dedi: arşiv sınıfında yalnız 400 Gi’lik bir birim var, istenen 500 Gi; hızlı sınıfında kalan en büyük birim 50 Gi, istenen 300 Gi. Bir talep sınıf yok dedi: cok-hizli diye bir sınıf bildiren tek bir birim bile yok.

Bu üç neden aynı işi gerektirmiyor ve ayırmak devrin ilk kazancıdır. Boyut reddi bir kapasite kararıdır: havuza daha büyük birim eklenir. Kip reddi bir arayüz kararıdır; hiçbir büyütme onu çözmez, çünkü çok düğüm yazar kipini sunmak depolamanın kendi özelliğidir. Sınıf reddi ise bir sözlük hatası olabilir: uygulama kümenin tanımadığı bir sınıf adı bildirmiştir. Karar devredildiğinde ret gerekçesinin makine tarafından üretilmesi gerekiyor, yoksa talep yalnız “bağlanmadı” der.

İkinci satır çifti seçim kuralının bedelini veriyor. İlk uyan birimi seçmekle yeterli olan en küçüğü seçmek karşılanan sayıyı değiştirmiyor, ikisinde de altı; değişen şey israftır: 85 Gi’ye karşı 75 Gi fazla ayırma. Büyük birimleri erken tüketen kural sonradan gelen büyük talepleri karşılayamaz hâle gelir. Seçim kuralı bugünkü kararı değil yarınki karşılanma oranını değiştiriyor, ve sistem yarın hangi taleplerin geleceğini bilmiyor.

Bağlama Kipi: Yerleştirmeden Elenen Düğümler

İkinci tablo, depolama kararının aslında bir yerleştirme kararı olduğunu gösteriyor. Bağlanan altı talep için altı düğümlük kümede 36 yerleştirme seçeneği vardı; kip ve topoloji birlikte bunların 26 tanesini eledi, geriye 10 seçenek kaldı.

Eleme kipe göre keskin biçimde ayrışıyor. Tek düğüm yazar kipindeki dört talebin birimi belirli bir düğüme bağlı; her biri için tek bir uygun düğüm kalıyor, beşi eleniyor. Çok düğüm okur ve çok düğüm yazar kipindeki iki talebin birimi bölge geneline açık; onlar için üç düğüm uygun, üçü eleniyor. Ortalama uygun düğüm sayısı tek yazar kipinde 1,00, ötekilerde 3,00.

Bunun sonucu, yerleştirmenin ilk sorusunun artık “hangi düğümde yer var” olmamasıdır. Kapsül tek düğüm yazar kipinde bir birim istediği anda düğüm zaten seçilmiştir; kalan tek soru o düğümde yeterli işlemci ve bellek bulunup bulunmadığıdır, bulunmazsa yerleştirme çözümsüz kalır ve başka düğüme kaçış yoktur. Devredilen karar iki sistemi birden bağlıyor: depolama eşlemesi zamanlayıcının seçim uzayını daraltıyor, zamanlayıcı da bu daralmayı bilmek zorunda. Bilmezse kapsülü uygun olmayan bir düğüme koyar, birim bağlanmaz, kapsül açılmaz.

Ölçüm ağında ayrım okunabilir bir kurala dönüşüyor: tarife tablosu bütün doğrulayıcı kopyalarınca okunduğu için çok düğüm okur kipiyle bildiriliyor ve üç düğüm uygun kalıyor; iş emri verisini tek bir yazar tuttuğu için tek yazar kipi onu bir düğüme çiviliyor.

Envanterin Yaşı ve Yanlış Bağlama

Üçüncü tablo devrin asıl bedelini veriyor. Eşleme kararı bildirilmiş bir envantere dayanıyor ve o envanter bir andan sonra gerçeği anlatmıyor.

Envanter yaşı sıfırken — yani karar anında havuzun gerçek doluluğu okunuyorken — yanlış bağlama yok: 21 talep doğru bağlandı, ortalama bekleme 0,33 tur. Yaş bir tura çıktığında doğru bağlama 15’e düşüyor ve 86 yanlış bağlama ortaya çıkıyor: sistem envanterde boş görünen bir birimi seçiyor, bağlama anında birimin dolu olduğu anlaşılıyor, talep kuyruğa dönüyor ve bir sonraki turda yeniden deneniyor. Yaş üç tura çıktığında doğru bağlama 10’a, yanlış bağlama 134’e gidiyor; ortalama bekleme 0,33 turdan 3,20 tura çıkıyor ve koşum sonunda hâlâ bekleyen talep sayısı 19’dan 30’a yükseliyor.

Karar verememe sütunu ters yönde hareket ediyor ve bu ilk bakışta yanıltıcıdır: 80’den 33’e iniyor. Sayı iyileşmiyor — eski envanterde havuz olduğundan boş göründüğü için sistem “uygun birim yok” demeyi bırakıp yanlış birim seçmeye başlıyor. Yani gecikmiş bilgi bir karar sınıfını başka bir karar sınıfına çeviriyor: dürüst bir “bilmiyorum” yerine yanlış bir “buldum” üretiyor. İkincisi daha pahalıdır, çünkü bağlama denemesi yapılıyor, başarısız oluyor ve tur harcanıyor.

Son sütun bedelin öbür ucudur. Yaş sıfırı sürdürmek tur başına 72 bildirim kalemi ister — havuzdaki 24 birimin üç kaleminin her turda yeniden okunması. Yaş üçte bu sayı 18’e iniyor, bildirim yükü dörtte bire düşüyor ve karşılığında yanlış bağlama sıfırdan 134’e çıkıyor. Bu ders için devrin bedeli tek satırda söylenebilir: eşleme kararının dayandığı 76 bilgi kalemi (10 talep × 3, 10 birim × 4, 6 düğüm × 1) sürekli ve zamanında üretilmezse, karar mekanizması değişmediği hâlde sonuç bozulur. Sistemin bilmediği şey birimin kim tarafından ne zaman bağlandığıdır; bilmediği için yaptığı şey, dolu bir birime bağlanmayı denemektir.

Özet

  • Talep ve arz ayrı bildirimlerdir: uygulama üç kalem, küme birim başına dört kalem bildirir; eşlemeyi depolama sürücü arayüzü yapar.
  • On talebin altısı karşılandı, dördü karşılanmadı ve nedenler ayrı sınıflardadır: boyut 2, kip 1, sınıf 1. Boyut bir kapasite kararı, kip bir arayüz kararı, sınıf bir sözlük hatasıdır.
  • Seçim kuralı karşılanan talep sayısını değiştirmiyor (ikisinde de 6), fazla ayrılan yeri değiştiriyor: ilk uyan 85 Gi, en küçük uyan 75 Gi.
  • Bağlama kipi bir yerleştirme kısıtıdır: 36 seçeneğin 26’sı elendi. Tek düğüm yazar kipinde talep başına ortalama 1,00 uygun düğüm kalıyor, çok düğüm kiplerinde 3,00.
  • Envanter yaşı 0 → 1 → 3 tur arttıkça doğru bağlama 21 → 15 → 10, yanlış bağlama 0 → 86 → 134, ortalama bekleme 0,33 → 1,93 → 3,20 tur. Bildirim yükü tur başına 72 → 36 → 18 kaleme iniyor.
  • Gecikmiş bilgi “karar verememe”yi (80 → 33) “yanlış karar”a çeviriyor: ucuz bilinmezlik yerine pahalı yanlış bağlama üretiliyor.

Sonraki Adım

Kalıcı veri kümede yerini buldu: talep bildiriliyor, arz eşleniyor, kapsül birimin erişilebildiği düğümde açılıyor. Ölçülen her şey tek bir talep ile tek bir birim arasındaydı. Oysa gecelik toplu işi besleyen doğrulayıcı tek kopya değil; üç kopya koşuyor ve her kopyanın kendi verisi var. Kopya kümesi kopyaları birbirinin yerine geçebilir sayar, adlarını da kalıcı tutmaz — o zaman bir kopya yeniden başladığında hangi birime bağlanacağını ne söyleyecek, ölçek küçültülünce hangi kopyanın verisi öksüz kalacak? Sonraki ders sıralı kimlik veren bir nesneyi sırasız kopya kümesiyle aynı olayda karşılaştırıyor ve şunları sayıyor: yeniden başlatmada kaç kopya aynı birime döndü, ölçek küçültmede hangi kopya gitti, sıralı başlatmanın tur maliyeti ne ve sıraya uyulmadığında küme üyeliğiyle veri sahipliği nasıl bozuluyor.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat