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
nodeiç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,arsivvecok-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.