Ders 04 / 14
Blok Depolama
Birim türü ve boyutunun bir giriş çıkış bütçesi vermesi: iş yükü profillerinin bu bütçeye uygulanması, doyma noktasının ve atıl bütçenin sayılması, boyutla başarımın birbirine bağlı olmasının açtığı tasarım tuzağı, birimin küçültülememesi ve tek örneğe bağlı olması.
İçindekiler
Önceki üç ders veriyi bütün hâlinde yazılıp okunan bir nesne olarak ele aldı. Kurgu ölçüm ağının toplayıcı süreci böyle çalışmaz: bir veritabanı dosyasının ortasındaki birkaç kilobaytı saniyede binlerce kez değiştirir. Birinci derste ölçülen 190 kat yazma büyütmesi bu iş yükünü nesne deposunda imkânsız kılar. Gereken şey, veriyi adreslenebilir bloklar hâlinde sunan ve üzerine bir dosya sistemi kurulabilen bir katmandır.
Bu türde kiralanan şey bir birimdir (volume). Birim bir örneğe takılır, işletim sistemi onu disk olarak görür. Devredilen taraf geniştir: fiziksel diskler, çoğaltma, bozuk sektör onarımı ve disk değişimi sağlayıcıdadır. Elde kalan taraf iki sayıya iner — tür ve boyut. Bu ikisinin bir üçüncüyü, giriş çıkış bütçesini belirlemesi dersin bütün ölçümlerinin kaynağıdır.
- DT19 — Birim türü kataloğu ve ücretler kurgudur; türler yetenekleriyle anılır.
- DT20 — Bir giriş çıkış işlemi, birimin saydığı taneye yuvarlanır: 16 KiB tane sayan türde 1 MiB’lik okuma 64 tane, 1 MiB tane sayan türde 1 tane tüketir.
- DT21 — İş yükü profilleri modeldir: işlem boyutu, işlem sayısı ve veri boyutu modelde yazılıdır.
// blok/model.mjs — blok birimi katalogu ve is yuku profilleri MODELDIR. Ucretler kurgu birimdir; // hicbir urun ya da birim ailesi adi kullanilmaz, turler yetenekleriyle anilir. export const TUR = { // birimKib: bu turun giris cikis islemini saydigi tane; ayar: is/s basina ucret "genel amacli": { birimKib: 16, gibBasi: 3, taban: 100, ustIs: 16000, mibGib: 0.25, ustMib: 250, ucret: 0.080, ayar: 0 }, "basarim ayarli": { birimKib: 16, gibBasi: 500, taban: 100, ustIs: 64000, mibGib: 1.00, ustMib: 1000, ucret: 0.125, ayar: 0.006 }, "verim ayarli": { birimKib: 1024, gibBasi: 0.5, taban: 12, ustIs: 500, mibGib: 0.40, ustMib: 1000, ucret: 0.045, ayar: 0 }, soguk: { birimKib: 1024, gibBasi: 0.2, taban: 12, ustIs: 250, mibGib: 0.12, ustMib: 250, ucret: 0.015, ayar: 0 }, }; // Is yuku profilleri: islem boyutu, saniyedeki islem, uzerinde durdugu veri. export const YUK = [ { ad: "sayac yazma", kib: 16, islem: 4200, veriGib: 200, cins: "rastgele kucuk yazma" }, { ad: "is emri sorgusu", kib: 8, islem: 900, veriGib: 60, cins: "rastgele kucuk okuma" }, { ad: "fatura uretimi", kib: 1024, islem: 180, veriGib: 400, cins: "sirali buyuk okuma" }, { ad: "foto yukleme", kib: 4096, islem: 25, veriGib: 1200, cins: "sirali buyuk yazma" }, ]; // Bir islem, turun saydigi taneye yuvarlanir: 16 KiB'lik yazma 1024 KiB'lik tanede de 1 tane yer. export const tane = (y, t) => Math.ceil(y.kib / t.birimKib); export const tuketilenIs = (y, t) => y.islem * tane(y, t); export const tuketilenMib = (y, t) => tuketilenIs(y, t) * t.birimKib / 1024; export const butce = (t, gib) => ({ is: Math.min(t.ustIs, Math.max(t.taban, Math.round(t.gibBasi * gib))), mib: Math.min(t.ustMib, t.mibGib * gib), }); export const ucret = (t, gib, ayarliIs = 0) => t.ucret * gib + t.ayar * ayarliIs;
Tür ve Boyut Bir Bütçe Verir
// blok/butce.mjs — birim turu ve boyutu bir butce verir; is yukleri bu butceye uygulanir import { TUR, YUK, tane, tuketilenIs, tuketilenMib, butce, ucret } from "./model.mjs"; const g = (x, n, d = 2) => x.toFixed(d).padStart(n); const s = (x, n) => String(x).padStart(n); console.log("is yuku | cins | islem boyutu | islem/s | ham MiB/s | veri GiB"); console.log("-----------------|----------------------|--------------|---------|-----------|---------"); for (const y of YUK) console.log(`${y.ad.padEnd(16)} | ${y.cins.padEnd(20)} | ${s(y.kib + " KiB", 12)} | ${s(y.islem, 7)} | ` + `${g(y.islem * y.kib / 1024, 9, 1)} | ${s(y.veriGib, 8)}`); const gen = TUR["genel amacli"]; console.log("\nveri boyutu kadar genel amacli birim alinirsa (dogal secim), tane 16 KiB:"); console.log("is yuku | butce is/s | tuketilen | doluluk | butce MiB/s | tuketilen | doluluk | doyan eksen"); console.log("-----------------|------------|-----------|---------|-------------|-----------|---------|------------"); for (const y of YUK) { const b = butce(gen, y.veriGib), dIs = tuketilenIs(y, gen) / b.is, dMib = tuketilenMib(y, gen) / b.mib; console.log(`${y.ad.padEnd(16)} | ${s(b.is, 10)} | ${s(tuketilenIs(y, gen), 9)} | %${g(100 * dIs, 6, 1)} | ` + `${g(b.mib, 11, 1)} | ${g(tuketilenMib(y, gen), 9, 1)} | %${g(100 * dMib, 6, 1)} | ` + `${(dIs >= dMib ? "is/s" : "MiB/s").padStart(11)}`); } const foto = YUK[3], bf = butce(gen, foto.veriGib); console.log(`atil butce: ${foto.ad} is/s ekseninde doyarken MiB/s butcesinin ` + `%${(100 * (1 - tuketilenMib(foto, gen) / bf.mib)).toFixed(1)}'i kullanilmiyor. Ayrica 8 KiB'lik okuma 16 KiB tane`); console.log(`tuketiyor: is emri sorgusunun ham ${(YUK[1].islem * YUK[1].kib / 1024).toFixed(1)} MiB/s'i butcede ` + `${tuketilenMib(YUK[1], gen).toFixed(1)} MiB/s yaziliyor.`); console.log("\nis yukunu karsilamak icin gereken en kucuk boyut ve aylik ucret (kurgu birim):"); console.log("is yuku | tur | tane/islem | gereken GiB | atil GiB | aylik ucret"); console.log("-----------------|-----------------|------------|-------------|----------|------------"); const enUcuz = {}; for (const y of YUK) for (const [ad, t] of Object.entries(TUR)) { let boyut = null; for (let gib = y.veriGib; gib <= 65536; gib += 4) { // butce yetene kadar boyut buyutulur const b = butce(t, gib); if (b.is >= tuketilenIs(y, t) && b.mib >= tuketilenMib(y, t)) { boyut = gib; break; } } if (ad === "basarim ayarli" && tuketilenMib(y, t) <= t.ustMib && tuketilenIs(y, t) <= t.ustIs) boyut = y.veriGib; if (boyut === null) { console.log(`${y.ad.padEnd(16)} | ${ad.padEnd(15)} | ${s(tane(y, t), 10)} | ${"karsilanamaz".padStart(11)} | ` + `${"-".padStart(8)} | ${"-".padStart(11)}`); continue; } const u = ucret(t, boyut, ad === "basarim ayarli" ? tuketilenIs(y, t) : 0); if (!enUcuz[y.ad] || u < enUcuz[y.ad].u) enUcuz[y.ad] = { ad, u, boyut }; console.log(`${y.ad.padEnd(16)} | ${ad.padEnd(15)} | ${s(tane(y, t), 10)} | ${s(boyut, 11)} | ` + `${s(boyut - y.veriGib, 8)} | ${g(u, 11)}`); } console.log("\nen ucuz secim: " + YUK.map((y) => `${y.ad} -> ${enUcuz[y.ad].ad} ${enUcuz[y.ad].boyut} GiB ` + `(${enUcuz[y.ad].u.toFixed(2)})`).join("; "));
is yuku | cins | islem boyutu | islem/s | ham MiB/s | veri GiB -----------------|----------------------|--------------|---------|-----------|--------- sayac yazma | rastgele kucuk yazma | 16 KiB | 4200 | 65.6 | 200 is emri sorgusu | rastgele kucuk okuma | 8 KiB | 900 | 7.0 | 60 fatura uretimi | sirali buyuk okuma | 1024 KiB | 180 | 180.0 | 400 foto yukleme | sirali buyuk yazma | 4096 KiB | 25 | 100.0 | 1200 veri boyutu kadar genel amacli birim alinirsa (dogal secim), tane 16 KiB: is yuku | butce is/s | tuketilen | doluluk | butce MiB/s | tuketilen | doluluk | doyan eksen -----------------|------------|-----------|---------|-------------|-----------|---------|------------ sayac yazma | 600 | 4200 | % 700.0 | 50.0 | 65.6 | % 131.3 | is/s is emri sorgusu | 180 | 900 | % 500.0 | 15.0 | 14.1 | % 93.8 | is/s fatura uretimi | 1200 | 11520 | % 960.0 | 100.0 | 180.0 | % 180.0 | is/s foto yukleme | 3600 | 6400 | % 177.8 | 250.0 | 100.0 | % 40.0 | is/s atil butce: foto yukleme is/s ekseninde doyarken MiB/s butcesinin %60.0'i kullanilmiyor. Ayrica 8 KiB'lik okuma 16 KiB tane tuketiyor: is emri sorgusunun ham 7.0 MiB/s'i butcede 14.1 MiB/s yaziliyor. is yukunu karsilamak icin gereken en kucuk boyut ve aylik ucret (kurgu birim): is yuku | tur | tane/islem | gereken GiB | atil GiB | aylik ucret -----------------|-----------------|------------|-------------|----------|------------ sayac yazma | genel amacli | 1 | 1400 | 1200 | 112.00 sayac yazma | basarim ayarli | 1 | 200 | 0 | 50.20 sayac yazma | verim ayarli | 1 | karsilanamaz | - | - sayac yazma | soguk | 1 | karsilanamaz | - | - is emri sorgusu | genel amacli | 1 | 300 | 240 | 24.00 is emri sorgusu | basarim ayarli | 1 | 60 | 0 | 12.90 is emri sorgusu | verim ayarli | 1 | karsilanamaz | - | - is emri sorgusu | soguk | 1 | karsilanamaz | - | - fatura uretimi | genel amacli | 64 | 3840 | 3440 | 307.20 fatura uretimi | basarim ayarli | 64 | 400 | 0 | 119.12 fatura uretimi | verim ayarli | 1 | 452 | 52 | 20.34 fatura uretimi | soguk | 1 | 1500 | 1100 | 22.50 foto yukleme | genel amacli | 256 | 2136 | 936 | 170.88 foto yukleme | basarim ayarli | 256 | 1200 | 0 | 188.40 foto yukleme | verim ayarli | 4 | 1200 | 0 | 54.00 foto yukleme | soguk | 4 | 1200 | 0 | 18.00 en ucuz secim: sayac yazma -> basarim ayarli 200 GiB (50.20); is emri sorgusu -> basarim ayarli 60 GiB (12.90); fatura uretimi -> verim ayarli 452 GiB (20.34); foto yukleme -> soguk 1200 GiB (18.00)
İkinci tablo doyma noktalarını veriyor. Veri boyutu kadar birim almak — en doğal seçim — dört iş yükünün dördünde de yetmiyor: doluluk yüzde 177,8 ile yüzde 960 arasında. Doyan eksen dördünde de iş/s’dir, ama nedenleri farklıdır. Sayaç yazma gerçekten çok işlem yapar; fatura üretimi saniyede yalnız 180 işlem yapar, her işlemi 64 tane tükettiği için bütçede 11.520 iş/s yazılır. Tane boyutu, iş yükünün bütçedeki görüntüsünü değiştirir.
Atıl bütçe aynı tablonun diğer yüzüdür. Foto yükleme iş/s ekseninde doyarken MiB/s bütçesinin yüzde 60’ı hiç harcanmaz. Ters yönde de kayıp vardır: 8 KiB’lik iş emri okuması 16 KiB’lik taneyi tümüyle tüketir, ham 7,0 MiB/s bütçede 14,1 MiB/s yazılır — işlem boyutunun tane boyutundan küçük olmasının doğrudan sonucu.
Üçüncü tablo tür seçimini bir hesaba indiriyor. Sıralı büyük okuma 1 MiB tane sayan türlerde 15 kat ucuza gelir: fatura üretimi genel amaçlı birimde 307,20, verim ayarlı birimde 20,34 birim tutar. Aynı türler rastgele küçük yazmayı ise karşılayamaz — 16 KiB’lik yazma 1 MiB’lik taneyi harcar, 4.200 işlem/s 4.200 MiB/s tüketim yazar. Yanlış tür burada pahalı değil, imkânsızdır.
Boyutla Başarımın Bağlı Olması
- DT22 — Başarım ayarlı türde iş/s ayrıca ücretlendirilir; diğer türlerde bütçe yalnız boyuta bağlıdır.
- DT23 — Birim büyütülebilir, küçültülemez; kopyalama hızı modelde 250 MiB/s’dir.
- DT24 — Birim tek örneğe ve tek bölgeye bağlıdır; anlık görüntü sıkışma oranı 0,55’tir.
// blok/tuzak.mjs — boyut ile basarimin bagli olmasi, kucultememe ve tek ornege baglilik sayilir import { TUR, YUK, tuketilenIs, butce, ucret } from "./model.mjs"; const gen = TUR["genel amacli"], sayac = YUK[0]; const CIKIS = { bolgelerArasi: 0.020, internet: 0.085 }; const SIKISMA = 0.55, HIZ_MIB = 250, BAGLAMA_SN = 40, TOPLAYICI = 12, YAZAR = 1; const g = (x, d = 2) => x.toFixed(d); const gerekenBoyut = (isS) => { // butce yetene kadar boyut buyutulur for (let gib = 4; gib <= 65536; gib += 4) if (butce(gen, gib).is >= isS) return gib; }; const ILK = gerekenBoyut(tuketilenIs(sayac, gen)), DUSEN = 900, YENI = gerekenBoyut(DUSEN); console.log(`${sayac.ad}: veri ${sayac.veriGib} GiB, gereken ${tuketilenIs(sayac, gen)} is/s.`); console.log(` genel amacli birimde is/s boyuta bagli oldugu icin ${ILK} GiB alinmali: ` + `${ILK - sayac.veriGib} GiB veri icin degil, butce icin duruyor (aylik ${g(ucret(gen, ILK))} birim).`); console.log(` ayni butce basarim ayarli turde ${sayac.veriGib} GiB ile aliniyor: aylik ` + `${g(ucret(TUR["basarim ayarli"], sayac.veriGib, tuketilenIs(sayac, gen)))} birim.`); console.log(`\nis yuku ${tuketilenIs(sayac, gen)} is/s'den ${DUSEN} is/s'ye dustu; artik ${YENI} GiB yeterli.`); console.log(` buyutme serbest: ${ILK} GiB birim veri tasimadan buyutulebilir.`); console.log(` kuculme yok: ${YENI} GiB'lik yeni birim acilir, ${sayac.veriGib} GiB kopyalanir, baglanti degistirilir.`); const kopyaSn = sayac.veriGib * 1024 / HIZ_MIB; console.log(` kopyalama ${g(kopyaSn / 60, 1)} dk (${HIZ_MIB} MiB/s), gecis boyunca iki birim birden faturalanir: ` + `${g(ucret(gen, ILK) + ucret(gen, YENI))} birim/ay.`); console.log(` kucultulemedigi icin odenen fark: aylik ${g(ucret(gen, ILK) - ucret(gen, YENI))}, ` + `yillik ${g(12 * (ucret(gen, ILK) - ucret(gen, YENI)))} birim.`); const anlik = sayac.veriGib * SIKISMA; console.log(`\nbirim tek ornege ve tek bolgeye baglidir: ${TOPLAYICI} toplayici ornekten ayni anda ${YAZAR} tanesi yazabilir.`); console.log(` baska ornege vermek sokup takmaktir; modelde baglama ${BAGLAMA_SN} sn, bu sure boyunca yazar yok.`); console.log(` baska bolgeye tasimak anlik goruntu ister: ${g(anlik, 1)} GiB (sikisma ${SIKISMA}); ` + `bolgeler arasi ${g(anlik * CIKIS.bolgelerArasi, 2)}, internete ${g(anlik * CIKIS.internet, 2)} birim cikis.`); console.log(` bolge ici anlik goruntu cikis ucreti dogurmaz; birimi bolgeden cikarmak dogurur.`);
sayac yazma: veri 200 GiB, gereken 4200 is/s. genel amacli birimde is/s boyuta bagli oldugu icin 1400 GiB alinmali: 1200 GiB veri icin degil, butce icin duruyor (aylik 112.00 birim). ayni butce basarim ayarli turde 200 GiB ile aliniyor: aylik 50.20 birim. is yuku 4200 is/s'den 900 is/s'ye dustu; artik 300 GiB yeterli. buyutme serbest: 1400 GiB birim veri tasimadan buyutulebilir. kuculme yok: 300 GiB'lik yeni birim acilir, 200 GiB kopyalanir, baglanti degistirilir. kopyalama 13.7 dk (250 MiB/s), gecis boyunca iki birim birden faturalanir: 136.00 birim/ay. kucultulemedigi icin odenen fark: aylik 88.00, yillik 1056.00 birim. birim tek ornege ve tek bolgeye baglidir: 12 toplayici ornekten ayni anda 1 tanesi yazabilir. baska ornege vermek sokup takmaktir; modelde baglama 40 sn, bu sure boyunca yazar yok. baska bolgeye tasimak anlik goruntu ister: 110.0 GiB (sikisma 0.55); bolgeler arasi 2.20, internete 9.35 birim cikis. bolge ici anlik goruntu cikis ucreti dogurmaz; birimi bolgeden cikarmak dogurur.
Tuzak ilk satırlarda duruyor. Genel amaçlı türde iş/s boyuta bağlı olduğu için 200 GiB’lik veri 1.400 GiB’lik birim ister: 1.200 GiB, veri için değil bütçe için durur. Aynı bütçe, iş/s’yi ayrıca satan türde 200 GiB ile 50,20 birime alınır — kapasiteyi başarım için satın almak, boş baytı her ay yeniden ödemektir.
İkinci blok geri alınamayan kalemi veriyor. İş yükü 4.200 iş/s’den 900’e düştüğünde 300 GiB yeterlidir, ama birim küçültülemez. Büyütmek veri taşımadan yapılır; küçültmek yeni birim açmak, 200 GiB kopyalamak, bağlantıyı değiştirmektir — modelde 13,7 dakika, geçiş boyunca çift faturalandırma ve yılda 1.056 birim fazla ödeme. Boyut tek yönlü bir kadrandır.
Üçüncü blok türün kendi sınırını yazıyor. Birim tek örneğe bağlıdır: on iki toplayıcı örnekten aynı anda yalnız biri yazabilir; başka bir örneğe vermek sökme ve takma işidir ve modelde kırk saniye boyunca hiçbir yazar yoktur. Birim tek bölgeye de bağlıdır, taşınması anlık görüntü ister — 110 GiB, bölgeler arası 2,20, internete 9,35 birim. Bölge içinde kalan anlık görüntü çıkış ücreti doğurmaz.
Özet
- Tür ve boyut birlikte bir giriş çıkış bütçesi verir; bütçe iş/s ve MiB/s eksenlerinde tükenir ve iş yükü hangisini önce doldurursa orada doyar.
- İşlem, birimin saydığı taneye yuvarlanır: 1 MiB’lik okuma 16 KiB tanede 64 tane tüketir; 8 KiB’lik okumanın ham 7,0 MiB/s’i bütçede 14,1 MiB/s görünür.
- Atıl bütçe ölçülür: foto yükleme iş/s ekseninde doyarken MiB/s bütçesinin yüzde 60’ı kullanılmaz. Yanlış tür kimi zaman pahalı değil imkânsızdır.
- Boyutla başarımın bağlı olması tuzaktır: 200 GiB veri için 1.400 GiB birim alınır, 1.200 GiB bütçe için durur. Aynı bütçe iş/s’yi ayrıca satan türde 112,00 yerine 50,20 birimdir.
- Geri alınamayan kalem boyuttur: birim büyütülebilir, küçültülemez. Küçültme yeni birim, 13,7 dakikalık kopyalama ve çift faturalandırma demektir.
Sonraki Adım
Son blok bir kapı bıraktı: on iki toplayıcı örnekten aynı anda yalnız biri yazabiliyor. Kurgu ölçüm ağında bu doğrudan bir engeldir — saha ekipleri iş emri eklerini aynı dizine bırakır, fatura üretimi aynı dizinden okur ve hepsi ayrı örneklerde koşar. Blok birimi bunu karşılayamaz, nesne deposu ise dizin ve kilit sunmaz. Sonraki ders üçüncü türü ölçer: aynı veriyi birden çok örneğin aynı anda bağladığı paylaşımlı dosya sistemi. Ölçülecek üç şey var — çok yazarlı erişimin üç türde nasıl değiştiği, kilidin ne kadar beklettiği, ve paylaşımlı dosya sisteminin hangi iş yükünde hiçbir şey kazandırmadığı.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.