Ders 04 / 10
Ölçeklenebilirlik Kararları
Ölçek biriminin sınırının nereye çizileceği: tüm sistem, servis ve kiracı adayları için kopyalanan bileşenin, paylaşılan kalan kaynağın ve kopyalanamayan tekil noktanın sayılması, ve kopyalama kuralının geçmiş ölçekleme denemelerinde yakaladığı, kaçırdığı, boşa öttüğü durumlar.
İçindekiler
Güven sınırı grafiği bölgeleri birbirinden ayırdı, ama her bölgenin kaç kopyasının koştuğunu söylemedi. Sistem büyüdüğünde bu soru öne çıkar ve genellikle yanlış biçimde sorulur. Kaç kopya gerektiği ve kapasitenin nasıl hesaplanacağı Başarım Karşıt Kalıpları ve İzleme kursunun Kapasite Planlama dersinde ölçüldü — düğüm sayısı, yük kısıtı ile arıza kısıtının büyüğüdür; burada tekrarlanmaz. Buradaki soru aritmetiğin öncesindedir ve tek cümledir: neyin kopyalanacağı.
Kopyalanan bütüne ölçek birimi denir. Terim, dağıtım damgası dersindeki terimin aynısıdır; oradaki soru birimin kaç kopyasının gerektiğiydi, buradaki soru birimin sınırının nereye çizileceği. Sınır farklı yerlere çizilebilir ve her çizim başka bir şeyi kopyalar, başka bir şeyi paylaşımda bırakır. Bu ders üç adayı yan yana koyup üç sayıyı çıkarır: kopyalanan bileşen, paylaşılan kalan kaynak, kopyalanamayan tekil nokta.
Üç Ölçek Birimi Adayı
Aşağıdaki blok, kurgusal bölgesel kütüphane ağının bileşenlerini, aralarındaki bağımlılıkları ve üç ölçek birimi adayını modelliyor. Ağ birden çok belediyeye hizmet veriyor; kiracı, bir belediyenin bütün şubeleri demek. Her aday, hangi bileşenin kopyalanacağını seçen bir kuraldır.
// birim.mjs — uc olcek birimi adayini modeller ve kopyalanani, paylasilani, tekili sayar import { mkdirSync, writeFileSync } from "node:fs"; // KN17: kurgusal bolgesel kutuphane aginin on dort bileseni. Ag birden cok belediyeye hizmet // veriyor; kiraci, bir belediyenin butun subeleri demek. Alanlar: [kod, ad, durum, // kiraciya bolunur mu, kopyalanamama nedeni]. Model. const BILESEN = [ ["C1", "odunc servisi", "durumsuz", true, ""], ["C2", "ucretlendirme servisi", "durumsuz", true, ""], ["C3", "uyelik servisi", "durumsuz", true, ""], ["C4", "bildirim gonderici", "durumsuz", true, ""], ["C5", "yonetim konsolu", "durumsuz", false, ""], ["C6", "arama dizini", "durumlu", true, ""], ["C7", "katalog onbellegi", "durumlu", false, ""], ["C8", "odunc veritabani", "durumlu", true, ""], ["C9", "uyelik veritabani", "durumlu", true, ""], ["C10", "ucret defteri", "durumlu", true, ""], ["C11", "dis katalog baglayicisi", "durumsuz", false, "tek dis sozlesme"], ["C12", "kimlik baglayicisi", "durumsuz", false, "tek dis sozlesme"], ["C13", "numara ureteci", "durumlu", false, "kuresel sira"], ["C14", "denetim kaydi deposu", "durumlu", false, "tek yazici yukumlulugu"], ]; // KN18: bilesenler arasindaki on sekiz bagimlilik [kaynak, hedef, tur]. Model. const BAGIMLILIK = [ ["C1", "C8", "yazar"], ["C1", "C9", "okur"], ["C1", "C13", "yazar"], ["C1", "C14", "yazar"], ["C1", "C7", "okur"], ["C2", "C10", "yazar"], ["C2", "C8", "okur"], ["C2", "C14", "yazar"], ["C3", "C9", "yazar"], ["C3", "C12", "okur"], ["C3", "C14", "yazar"], ["C4", "C8", "okur"], ["C4", "C9", "okur"], ["C5", "C14", "okur"], ["C5", "C10", "okur"], ["C6", "C7", "okur"], ["C11", "C7", "yazar"], ["C11", "C6", "yazar"], ]; // Olcek birimi, es zamanli olarak birden cok kopyasi kosturulan butundur. Terim, dagitim // damgasi dersindekiyle aynidir; orada birimin kac kopyasinin gerektigi hesaplaniyordu, // burada birimin sinirinin nereye cizilecegi sorusu var. const ADAY = { "tum sistem": (b) => b[4] === "", servis: (b) => b[4] === "" && b[2] === "durumsuz", kiraci: (b) => b[4] === "" && b[3], }; const tekil = BILESEN.filter((b) => b[4] !== ""); const bul = (k) => BILESEN.find((b) => b[0] === k); mkdirSync("model", { recursive: true }); writeFileSync("model/model.mjs", `export const BILESEN = ${JSON.stringify(BILESEN)};\n` + `export const BAGIMLILIK = ${JSON.stringify(BAGIMLILIK)};\n` + `export const ADAY = ${JSON.stringify(Object.keys(ADAY))};\n`); console.log(`${BILESEN.length} bilesen, ${BAGIMLILIK.length} bagimlilik, ` + `${BAGIMLILIK.filter((e) => e[2] === "yazar").length} tanesi yazma`); console.log(`\n${"olcek birimi adayi".padEnd(20)}${"kopyalanan".padStart(11)}` + `${"paylasilan".padStart(11)}${"tekil".padStart(7)}${"paylasilana giren bagimlilik".padStart(29)}`); for (const [ad, secim] of Object.entries(ADAY)) { const kopya = BILESEN.filter(secim); const paylasilan = BILESEN.filter((b) => b[4] === "" && !secim(b)); const giren = BAGIMLILIK.filter(([, h]) => paylasilan.some((p) => p[0] === h)).length; console.log(`${ad.padEnd(20)}${String(kopya.length).padStart(11)}` + `${String(paylasilan.length).padStart(11)}${String(tekil.length).padStart(7)}` + `${String(giren).padStart(29)}`); } console.log(`\nhicbir adayda kopyalanamayan tekil nokta (${tekil.length}):`); for (const b of tekil) console.log(` ${b[0].padEnd(4)}${b[1].padEnd(26)}${b[4]}`); const tekileGiden = BAGIMLILIK.filter(([, h]) => tekil.some((t) => t[0] === h)); console.log(`tekil noktalara giden bagimlilik ${tekileGiden.length}, ` + `bunlarin ${tekileGiden.filter((e) => e[2] === "yazar").length} tanesi yazma; ` + `yazan bilesenler: ${[...new Set(tekileGiden.filter((e) => e[2] === "yazar") .map((e) => bul(e[0])[1]))].join(", ")}`);
14 bilesen, 18 bagimlilik, 9 tanesi yazma olcek birimi adayi kopyalanan paylasilan tekil paylasilana giren bagimlilik tum sistem 10 0 4 0 servis 5 5 4 12 kiraci 8 2 4 3 hicbir adayda kopyalanamayan tekil nokta (4): C11 dis katalog baglayicisi tek dis sozlesme C12 kimlik baglayicisi tek dis sozlesme C13 numara ureteci kuresel sira C14 denetim kaydi deposu tek yazici yukumlulugu tekil noktalara giden bagimlilik 6, bunlarin 4 tanesi yazma; yazan bilesenler: odunc servisi, ucretlendirme servisi, uyelik servisi
Üç adayın kopyalanan sütunu birbirinden farklı: tüm sistem on bileşen kopyalıyor, kiracı sekiz, servis beş. Ama tekil sütunu üç adayda da dört. Ölçek birimini değiştirmek tekil noktaları değiştirmiyor. Sınır nereye çizilirse çizilsin dört bileşen tek kopya kalıyor, çünkü bunların kopyalanamama nedeni birimin sınırıyla ilgili değil: ikisi tek dış sözleşmeye bağlı, biri küresel bir sıra üretiyor, biri tek yazıcı yükümlülüğü taşıyor. Son ikisi teknik kısıt, ilk ikisi değil. Sözleşmeden gelen tekillik bir mimari kararla çözülmez; başka bir kararla, sözleşmeyi değiştirerek çözülür ve bu ölçek birimi tartışmasının dışındadır.
Asıl bedeli son sütun gösteriyor. Servis adayı en az bileşeni kopyalıyor ve paylaşımda kalan kaynağa giren on iki bağımlılık bırakıyor; kiracı adayı üç, tüm sistem adayı sıfır bırakıyor. Kopyalanan bileşen sayısı ile paylaşımda kalan yük ters yönde hareket ediyor, ve bu ilişki adayların gerçek karşılaştırmasıdır: servis adayı ucuz kopyalanır ama on iki bağımlılığı ortak kaynağa dayar; her biri kopyalar arttıkça darboğaz adayıdır.
Tüm sistem adayının sıfırı dikkatli okunmalı. Sıfır, paylaşımın kalmadığı anlamına gelmiyor; o adayda paylaşılan sütunu boş çünkü paylaşılan her şey tekil sütununa geçti. Dört tekil noktaya giden altı bağımlılığın dördü yazma ve yazanlar üç ayrı servis. Yani hangi aday seçilirse seçilsin, üç servis tek kopya kalan bir bileşene yazmaya devam ediyor. Ölçek birimi seçimi bu üç yazmayı ortadan kaldırmıyor, yalnız hangi sınırın içinde göründüklerini değiştiriyor.
Kopyalama Kuralı
Üç sütun bir tablo doldurur; sıradaki soru bunun koşturulabilir bir kurala çevrilip çevrilemeyeceğidir. Kural şöyle yazılabilir: bir ölçek biriminin içindeki bileşen, birimin dışındaki durumlu bir bileşene yazmamalı. Yazıyorsa birimin iki kopyası aynı duruma eş zamanlı dokunur. Aşağıdaki blok bu kuralı yazıyor ve geçen yıl denenmiş on ölçekleme adımında koşturuyor.
// denetim.mjs — olcek birimi kuralini yazar ve gecmis olcekleme denemelerinde kosturur import { BILESEN, BAGIMLILIK } from "./model/model.mjs"; const bul = (k) => BILESEN.find((b) => b[0] === k); const SECIM = { "tum sistem": (b) => b[4] === "", servis: (b) => b[4] === "" && b[2] === "durumsuz", kiraci: (b) => b[4] === "" && b[3], }; // Servis adayinda birim tek bir servistir; oteki iki adayda birim, adayin sectigi butun // bilesenlerdir. Kural: birim icindeki bir bilesen, birim disindaki durumlu bir bilesene // yazmamali. Yazarsa kopyalar ayni duruma es zamanli dokunur. const birim = (aday, bilesen) => (aday === "servis" ? [bilesen] : BILESEN.filter(SECIM[aday]).map((b) => b[0])); const ihlalKenari = (u) => BAGIMLILIK.filter(([k, h, t]) => t === "yazar" && u.includes(k) && !u.includes(h) && bul(h)[2] === "durumlu"); // KN19: bilinen ihlal kumesi — gecen bir yilda denenmis on olcekleme adimi ve gercek sonucu // [aday, bilesen, sonuc, not]. Model. const DENEME = [ ["servis", "C1", "sorun", "kuresel odunc numarasina iki kopyadan yazma"], ["servis", "C2", "sorun", "ucret defterine cift kayit"], ["servis", "C3", "sorun", "uyelik veritabanina cift yazma"], ["servis", "C4", "sorunsuz", "yalniz okuyor"], ["servis", "C5", "sorunsuz", "yalniz okuyor"], ["servis", "C6", "sorunsuz", "dizin kopya basina yeniden uretiliyor"], ["servis", "C7", "sorun", "iki kopya ayni yerel disk yolunu paylasiyor"], ["servis", "C11", "sorun", "tek dis sozlesme iki kopyayi kaldirmiyor"], ["kiraci", "", "sorunsuz", "yazmalar kiraci anahtarina bolunmus, denetim kaydi eklemeli"], ["tum sistem", "", "sorun", "denetim kaydi deposuna iki damgadan yazma"], ]; console.log(`${"aday".padEnd(12)}${"birim".padEnd(26)}${"kural".padEnd(11)}` + `${"gercek".padEnd(10)}sonuc`); let yakalanan = 0, kacan = 0, yanlis = 0, sessizlik = 0; for (const [aday, kod, gercek, not] of DENEME) { const u = birim(aday, kod); const kenar = ihlalKenari(u); const oter = kenar.length > 0; const sonuc = oter && gercek === "sorun" ? "yakalanan" : oter ? "yanlis alarm" : gercek === "sorun" ? "kacan" : "dogru sessizlik"; if (sonuc === "yakalanan") yakalanan += 1; else if (sonuc === "kacan") kacan += 1; else if (sonuc === "yanlis alarm") yanlis += 1; else sessizlik += 1; console.log(`${aday.padEnd(12)}${(kod ? bul(kod)[1] : "adayin tumu").padEnd(26)}` + `${(oter ? `oter (${kenar.length})` : "susar").padEnd(11)}${gercek.padEnd(10)}${sonuc}`); } console.log(`\n${DENEME.length} deneme, ${DENEME.filter((d) => d[2] === "sorun").length} sorunlu: ` + `yakalanan ${yakalanan}, kacan ${kacan}, yanlis alarm ${yanlis}, dogru sessizlik ${sessizlik}`); for (const d of DENEME) { const oter = ihlalKenari(birim(d[0], d[1])).length > 0; if ((oter && d[2] === "sorunsuz") || (!oter && d[2] === "sorun")) console.log(` ${oter ? "yanlis alarm" : "kacan"}: ${d[0]}/${d[1] ? bul(d[1])[1] : "tumu"} — ${d[3]}`); } // KN20: cevrilemeyen kisim. Kural bildirilen bagimliliklara bakar; iki kopyanin bildirilmeyen // bir kaynagi (ayni disk yolu, ayni surec, ayni zamanlayici) paylasmasini goremez. Yerine // kopyalama sinamasi konur: iki kopya yan yana kosturulup cakisma gozlenir, deneme basina // 6 kisi-saat. Sinama, kacan denemeyi kopyalar acilir acilmaz gosterir. const SAAT = 6; console.log(`\ncevrilemeyen: bildirilmeyen paylasilan kaynak; kacan ${kacan} denemenin nedeni bu`); console.log(`yerine konan: kopyalama sinamasi, ${DENEME.length} deneme x ${SAAT} = ` + `${DENEME.length * SAAT} kisi-saat; sinama kacani yakalar, yanlis alarmi da ayirir`); const alan = BILESEN.length * 5 + BAGIMLILIK.length * 3; console.log(`kural maliyeti: elle bildirilen ${alan} alan (${BILESEN.length} bilesen x 5, ` + `${BAGIMLILIK.length} bagimlilik x 3); kosum ${DENEME.length * BAGIMLILIK.length} kenar ` + `karsilastirmasi; bildirim eskirse kacan artar`);
aday birim kural gercek sonuc servis odunc servisi oter (3) sorun yakalanan servis ucretlendirme servisi oter (2) sorun yakalanan servis uyelik servisi oter (2) sorun yakalanan servis bildirim gonderici susar sorunsuz dogru sessizlik servis yonetim konsolu susar sorunsuz dogru sessizlik servis arama dizini susar sorunsuz dogru sessizlik servis katalog onbellegi susar sorun kacan servis dis katalog baglayicisi oter (2) sorun yakalanan kiraci adayin tumu oter (4) sorunsuz yanlis alarm tum sistem adayin tumu oter (4) sorun yakalanan 10 deneme, 6 sorunlu: yakalanan 5, kacan 1, yanlis alarm 1, dogru sessizlik 3 kacan: servis/katalog onbellegi — iki kopya ayni yerel disk yolunu paylasiyor yanlis alarm: kiraci/tumu — yazmalar kiraci anahtarina bolunmus, denetim kaydi eklemeli cevrilemeyen: bildirilmeyen paylasilan kaynak; kacan 1 denemenin nedeni bu yerine konan: kopyalama sinamasi, 10 deneme x 6 = 60 kisi-saat; sinama kacani yakalar, yanlis alarmi da ayirir kural maliyeti: elle bildirilen 124 alan (14 bilesen x 5, 18 bagimlilik x 3); kosum 180 kenar karsilastirmasi; bildirim eskirse kacan artar
On denemenin altısı sorun çıkarmıştı. Kural beşini yakalıyor, birini kaçırıyor, bir kez boşa ötüyor ve üç kez doğru susuyor. Doğru sessizlik ayrı sayılıyor çünkü bir kuralın değeri yalnız ateşlemelerinde değil: bildirim göndericisi, yönetim konsolu ve arama dizini denemelerinde kural sustu ve üçünde de sorun çıkmadı. Yalnız ateşlemeler sayılsaydı kuralın isabeti beş bölü altı görünürdü; sessizlikler de sayıldığında sekiz bölü on.
Kaçan deneme katalog önbelleği. İki kopya aynı yerel disk yolunu paylaştığı için çakıştılar, ama bu paylaşım bağımlılık listesinde yok — çünkü liste bileşenler arası bağımlılıkları taşıyor, bir bileşenin ortamıyla kurduğu bağı değil. Kural bildirilen bağımlılıklara bakar; bildirilmeyen paylaşım kuralın dışındadır, ve bu kuralın duyarlılığıyla değil kapsamıyla ilgilidir.
Yanlış alarm kiracı adayında çıkıyor. Kural doğru bir şey görüyor: kiracı birimi içindeki bileşenler birim dışındaki dört durumlu noktaya yazıyor. Ama yazmaların hepsi kiracı anahtarına bölünmüş ya da denetim kaydına eklemeli, yani iki kopya aynı satıra dokunmuyor. Kural yazmanın varlığını görüyor, yazmanın biçimini görmüyor. Bölünmüş yazma ile çakışan yazmayı ayırmak için bağımlılık kaydına bir alan daha eklemek gerekir, ve bu alan her bağımlılık için elle doldurulur.
Bir de doğru sonucun yanlış gerekçeyle geldiği bir satır var. Dış katalog bağlayıcısı denemesinde kural öttü ve deneme gerçekten sorun çıkardı, ama nedeni kuralın gösterdiği yazma kenarı değil, tek dış sözleşmeydi. Kuralın işaret ettiği kenar düzeltilseydi sorun aynen sürerdi. Yakalanan sayısı, gerekçenin doğruluğunu ölçmez; bu ayrım ancak her yakalamanın nedeni okunduğunda görünür.
Kuralın çevrilemeyen kısmı bildirilmeyen paylaşılan kaynaktır ve kaçan tek denemenin nedeni tam olarak budur. Yerine kopyalama sınaması konuyor: iki kopya yan yana koşturulup çakışma gözleniyor, deneme başına altı kişi-saat, on denemede 60 kişi-saat. Sınama kaçanı kopyalar açılır açılmaz gösterir ve yanlış alarmı da ayırır, çünkü bölünmüş yazmada çakışma gözlenmez. Kuralın kendi maliyeti başka bir kalemdir: on dört bileşen ve on sekiz bağımlılık için elle bildirilen 124 alan. Koşum 180 kenar karşılaştırması, yani ölçülecek bir bedel taşımıyor; bildirimin eskimesi ise doğrudan kaçana dönüşüyor.
Özet
- Ölçek birimi, eş zamanlı olarak birden çok kopyası koşan bütündür; bu derste sorulan, birimin kaç kopyasının gerektiği değil sınırının nereye çizileceğidir.
- Üç aday kopyalananda ayrışıyor (tüm sistem 10, kiracı 8, servis 5) ama tekilde ayrışmıyor: üçünde de dört bileşen kopyalanamıyor, ikisinin nedeni teknik değil sözleşmeye bağlı.
- Kopyalanan ile paylaşımda kalan ters yönde hareket ediyor: servis adayı en az kopyalayıp ortak kaynağa giren on iki bağımlılık bırakıyor, kiracı üç, tüm sistem sıfır.
- Kopyalama kuralı on denemede 5 yakalanan, 1 kaçan, 1 yanlış alarm, 3 doğru sessizlik veriyor; kaçanın nedeni duyarlılık değil kapsam, yanlış alarmın nedeni yazmanın biçiminin görülmemesi.
- Bir yakalamada gerekçe yanlış: kural yazma kenarını gösterdi, sorunun nedeni tek dış sözleşmeydi; çevrilemeyen kısmın yerine konan kopyalama sınaması on denemede 60 kişi-saat.
Sonraki Adım
Buraya kadar sayılan her şey — nitelik ağacı, gerilim matrisi, güven sınırı grafiği, ölçek birimi — sistemi değiştirmeyi gerektiriyor. Değiştirmenin kendisi hiç ölçülmedi. Sonraki ders aynı değişiklik kümesini iki ayrı yapı üzerinde koşturur ve değişiklik başına dokunulan dosyayı, dokunulan modülü ve değişikliğin kaç adım öteye yayıldığını sayar. Sonra ölçütlerin kendisini sınar: bu sayılar zaman içinde bozulmayı gösteriyor mu, yoksa yapı kötüleşirken sabit mi kalıyorlar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.