Ders 14 / 15
Lider Seçimi
Tekil sorumluluk gerektiren bir görevin tek düğüme verilmesi: kira süresine dayalı lider seçiminin süreç içi modelle kurulması, devralma turunun ve iki liderin aynı anda çalıştığı tur sayısının ölçülmesi, kira süresi uzadıkça lidersiz turun büyümesi, çitlemenin çift başlatmayı kaldırması, kalıcı tetiğin kaçırılan partiyi kurtarması ve sonuçların K01'in günlük fatura satırına çevrilmesi.
İçindekiler
Önceki dersin denetçisi tek bir taraf sayıldı. Gerçekte denetçi de, gün sonu işini başlatan zamanlayıcı da birden çok düğümde koşar — çünkü tek düğümde koşan bir denetçi, düştüğünde kimsenin fark etmediği bir iş akışının kendisi olur. Ama zamanlayıcının işi tekildir: gün sonu ücretlendirmesi bir kez başlatılmalıdır. İki düğüm aynı anda başlatırsa aynı satıcı-gün için iki fatura satırı üretilir ve bu, telafiyle değil ancak elle düzeltilir.
Lider seçimi (leader election), bir düğüm kümesinden yalnız birine belirli bir süre için sorumluluk veren düzenektir. Sistem Tasarımına Giriş kursunda ölçülen devralmayla akrabadır ama sorusu farklıdır: orada devralma hizmeti sürdürmek için yapılıyordu — yazma kabul eden bir kopya kalmalıydı; burada seçim tekil sorumluluk için yapılır — işi yapan yalnız bir taraf olmalıdır. Birincisinin başarısızlığı kesinti, ikincisininki çift iştir.
Kira Süresi ve Çitleme Belirteci
Sorumluluk süresizce verilmez, çünkü sorumluluğu alan düğümün düştüğünü kimse kesin olarak bilemez. Bunun yerine bir kira süresi (lease) tanınır: lider, paylaşılan kalıcı kayda düzenli aralıklarla imzasını atar. Kayıt kira süresi kadar tazelenmemişse başka bir düğüm sorumluluğu üstlenir ve kayıttaki çitleme belirteci (fencing token) adlı sayacı bir artırır. Belirteç, bir liderliğin kaçıncı sırada verildiğini söyler; ücretlendirmenin otuz günlük dönemiyle ilgisi yoktur.
Kira süresi düşen bir düğümü ayakta olan bir düğümden ayırt etmez; yalnız yazamayan bir düğümü ayırt eder. Duraklamış, ağdan kopmuş ya da yavaşlamış bir lider hâlâ ayaktadır ve kendini lider sanmaya devam eder. Bu yüzden asıl ölçülecek sayı devralma turu değil, iki düğümün aynı anda kendini lider saydığı tur sayısıdır. Modelde 5 düğüm vardır, ilk lider altıncı turdan itibaren beş tur boyunca ulaşılamaz kalır ve gün sonu partisi her altı turda bir başlatılmalıdır.
// lider/secim.mjs — kira suresine dayali lider secimi; tur tabanli surec ici model. Tur soyut // bir adimdir; duraklama, kira ve yenileme aralik parametreleridir, olculmus sureler degildir. export const TETIK = [6, 12, 18, 24]; // gun sonu partisinin baslatilmasi gereken turlar export const BAS = 6; // liderin ulasilamaz kaldigi ilk tur export function kosum({ dugum = 5, kira = 3, yenileme = 3, duraklama = 5, citleme = false, kaliciTetik = false, tur = 24 }) { const bit = BAS + duraklama - 1; const kayit = { lider: 0, sonYenileme: 0, belirtec: 1 }; // paylasilan kalici kayit const inanan = new Array(dugum).fill(false); inanan[0] = true; const belirtec = new Array(dugum).fill(0); belirtec[0] = 1; const s = { baslatilan: 0, kacirilan: 0, ciftBaslatma: 0, reddedilen: 0, gecikmeliTur: 0, ikiLiderliTur: 0, lidersizTur: 0, devralmaTuru: 0, devralma: 0 }; let bekleyen = 0, bekleyenTur = 0; const ulasilir = (d, t) => d !== 0 || t < BAS || t > bit; for (let t = 1; t <= tur; t++) { if (ulasilir(kayit.lider, t)) kayit.sonYenileme = t; // lider kirasini yeniliyor if (t - kayit.sonYenileme >= kira) { // kira doldu: bir dugum ustleniyor const yeni = [...Array(dugum).keys()].find((d) => d !== kayit.lider && ulasilir(d, t)); s.devralmaTuru += t - kayit.sonYenileme; s.devralma += 1; kayit.lider = yeni; kayit.sonYenileme = t; kayit.belirtec += 1; inanan[yeni] = true; belirtec[yeni] = kayit.belirtec; } const calisan = [...Array(dugum).keys()].filter((d) => inanan[d] && ulasilir(d, t)); if (calisan.length > 1) s.ikiLiderliTur += 1; if (calisan.length === 0) s.lidersizTur += 1; let kabul = 0; for (const d of calisan) { if (citleme && belirtec[d] < kayit.belirtec) { s.reddedilen += 1; continue; } // eski belirtec kabul += 1; } if (TETIK.includes(t)) { // gun sonu partisi baslatilmali if (kabul === 0) { if (kaliciTetik) { bekleyen += 1; bekleyenTur = t; } else s.kacirilan += 1; } else { s.baslatilan += 1; s.ciftBaslatma += kabul - 1; } } else if (bekleyen > 0 && kabul > 0) { // kalici tetik: yeni lider devraliyor s.baslatilan += 1; s.gecikmeliTur += t - bekleyenTur; bekleyen = 0; } if (t % yenileme === 0) for (const d of calisan) // dugum kaydi okur, gerekirse birakir if (kayit.lider !== d) inanan[d] = false; } return s; }
Modelin iki eklenti seçeneği var. Çitleme, her işin bu belirteçle birlikte yapılmasıdır: kayıt, belirteci geride kalmış bir düğümün işini reddeder. Çitleme İlişkisel Veritabanı Yönetimi kursunda kurulmuştu; burada tekil sorumluluğa uygulanır. Kalıcı tetik, lidersiz bir turda gelen başlatma isteğinin bir kayda düşürülmesi ve sonraki liderin onu üstlenmesidir.
// lider/olc.mjs — citlemesiz ve citlemeli kosum, sonra kira suresinin taranmasi import { kosum, TETIK, BAS } from "./secim.mjs"; const D = [["yalin", kosum({})], ["citleme", kosum({ citleme: true })], ["citleme+kalici tetik", kosum({ citleme: true, kaliciTetik: true })]]; const OLCU = [["baslatilan", "baslatilan parti"], ["kacirilan", "kacirilan parti"], ["gecikmeliTur", "gecikmeli baslama turu"], ["ciftBaslatma", "cift baslatilan parti"], ["reddedilen", "citlemeyle reddedilen"], ["ikiLiderliTur", "iki liderli tur"], ["lidersizTur", "lidersiz tur"], ["devralmaTuru", "devralma turu"]]; console.log(`5 dugum, 24 tur, kira 3, yenileme 3; lider dugum ${BAS}-${BAS + 4}. turlarda ` + `ulasilamaz. Gun sonu partisi tetigi: ${TETIK.join(", ")}. turlar`); console.log(); console.log(`${"olcu".padEnd(24)}${D.map(([a]) => a.padStart(22)).join("")}`); for (const [k, ad] of OLCU) console.log(`${ad.padEnd(24)}${D.map(([, r]) => String(r[k]).padStart(22)).join("")}`); const S = ["devralmaTuru", "lidersizTur", "kacirilan", "ikiLiderliTur", "ciftBaslatma"]; const bas = ["devr.turu", "lidersiz", "kacirilan", "iki lider", "cift"]; console.log(`\n${"".padStart(5)}${"uzun duraklama (5 tur)".padStart(50)}${"kisa duraklama (2 tur)".padStart(50)}`); console.log(`${"kira".padStart(5)}${bas.map((a) => a.padStart(10)).join("").repeat(2)}`); for (const kira of [2, 3, 5, 8]) { const satir = [5, 2].flatMap((duraklama) => { const r = kosum({ kira, duraklama, citleme: false }); return S.map((k) => String(r[k]).padStart(10)); }); console.log(`${String(kira).padStart(5)}${satir.join("")}`); }
5 dugum, 24 tur, kira 3, yenileme 3; lider dugum 6-10. turlarda ulasilamaz. Gun sonu partisi tetigi: 6, 12, 18, 24. turlar
olcu yalin citleme citleme+kalici tetik
baslatilan parti 3 3 4
kacirilan parti 1 1 0
gecikmeli baslama turu 0 0 2
cift baslatilan parti 1 0 0
citlemeyle reddedilen 0 2 2
iki liderli tur 2 2 2
lidersiz tur 2 2 2
devralma turu 3 3 3
uzun duraklama (5 tur) kisa duraklama (2 tur)
kira devr.turu lidersiz kacirilan iki lider cift devr.turu lidersiz kacirilan iki lider cift
2 2 1 1 2 1 2 1 1 2 0
3 3 2 1 2 1 0 2 1 0 0
5 5 4 1 2 1 0 2 1 0 0
8 0 5 1 0 0 0 2 1 0 0
Sayıların Okunması
Yalın koşum dört tetikten yalnız üçünü başlatabildi. Altıncı turda lider ulaşılamaz duruma geldi ve kira henüz dolmadığı için kimse yerine geçmedi: parti hiç başlamadı. Devralma üçüncü turda tamamlandı ve iki tur lidersiz geçti. On birinci turda eski lider geri döndü ve hâlâ kendini lider sanıyordu; on ikinci turdaki tetiği o da, yeni lider de gördü ve parti iki kez başlatıldı. Yalın düzenin bilançosu şudur: bir parti kaçtı, bir parti iki kez koştu, biri de doğru koştu.
Üç satır birbirinden ayrı tutulmalı. iki liderli tur iki düğümün kendini lider saydığı
tur sayısıdır ve üç sütunda da 2’dir; çitleme bu sayıyı değiştirmez, çünkü çitleme bir düğümün
inancını düzeltmez. Değişen cift baslatilan parti satırıdır: 1’den 0’a iniyor ve karşılığında
citlemeyle reddedilen 0’dan 2’ye çıkıyor. Kayıt, belirteci geride kalmış düğümün işini reddetti.
İnanç ile etki arasındaki bu ayrım kalıbın çekirdeğidir: lider seçimi kimin lider olduğunu
belirler, çitleme kimin yazabileceğini belirler. İkincisi olmadan birincisi yeterli değildir.
Üçüncü sütun ikinci hatayı kapatıyor. Kalıcı tetikle kaçırılan parti 0’a iniyor, başlatılan parti 3’ten 4’e çıkıyor ve bedel iki turluk bir gecikme oluyor. Tetiğin anlık olması onu bir zamana bağlar; kayda düşülmesi bir işe çevirir. Bu, önceki dersin zamanlayıcısının aynı kuralıdır: bellekte duran bir niyet arızayı geçemez.
Alttaki tablo kira süresinin ne satın aldığını gösteriyor. Kira 2’den 5’e çıktıkça devralma
turu 2’den 5’e, lidersiz tur 1’den 4’e çıkıyor; kira 8 olduğunda devralma hiç olmuyor ve
duraklama boyunca 5 tur lidersiz geçiyor. Buna karşılık iki lider sütunu kira 2, 3 ve 5’te
aynı — 2. Uzun kira iki liderli pencereyi daraltmıyor, çünkü o pencere kira süresinden
değil, geri dönen düğümün kaydı ne zaman yeniden okuduğundan doğuyor. Kira 8’de sütunun 0
olması bir kazanç değil: orada hiç devralma olmadığı için ikinci lider hiç ortaya çıkmadı ve
sistem beş tur boyunca sorumsuz kaldı.
Sağdaki blok kısa duraklamayı gösteriyor: iki turluk bir yavaşlamada kira 3 ve üstü hiç devralma üretmiyor, kira 2 ise gereksiz bir devralma ve iki liderli iki tur üretiyor. Kısa kira geçici yavaşlamayı arıza sanar; uzun kira gerçek arızayı geç fark eder. Ayarın doğru yeri bu ikisinin arasındadır ve kararın ölçüsü lidersiz turla iki liderli turun toplamıdır.
Hesaba Dönüş
Modelin turları K01’in sayılarına iki adımda bağlanır. Modelin verdiği şey pencere payıdır: bir devralmanın olduğu koşumda turların 2/24’ü lidersiz, 2/24’ü iki liderli geçti. Tetiğin bu pencerelere düşme oranı, tetiğin turlar arasında düzgün dağıldığı okumasıyla aynı paydır.
KK4 — yılda 6 devralma. Bu varsayım yeni değildir: Sistem Tasarımına Giriş kursunun Erişilebilirlik Kalıpları dersinde devralma penceresi isteğe çevrilirken aynı sayı kullanılmıştı ve burada aynı gerekçeyle sürdürülür. K01’in varsayım tablosuna eklenmez; duyarlılığı 12 ile hesaplanır. Bir gün sonu partisi K01’in hesabına göre 4000 fatura satırı üretir.
// lider/hesap.mjs — modelin pencere oranlarini K01'in gun sonu partisine cevirir import { kosum } from "./secim.mjs"; const FATURA_SATIRI = 4000; // K01: gunluk fatura satiri (hesap) = bir gun sonu partisi const TUR = 24; const y = kosum({}), c = kosum({ citleme: true, kaliciTetik: true }); const lidersizPay = y.lidersizTur / TUR, ikiLiderliPay = y.ikiLiderliTur / TUR; console.log(`model penceresi: lidersiz ${y.lidersizTur}/${TUR} = ${lidersizPay.toFixed(4)}, ` + `iki liderli ${y.ikiLiderliTur}/${TUR} = ${ikiLiderliPay.toFixed(4)}`); console.log(`bir parti = ${FATURA_SATIRI} fatura satiri (K01, hesap)`); console.log(); console.log(`${"KK4".padStart(5)}${"kacirilan parti/yil".padStart(21)}${"uretilmeyen satir".padStart(19)}` + `${"cift parti/yil".padStart(16)}${"cift satir".padStart(12)}`); for (const KK4 of [6, 12]) { // KK4: yilda kac devralma (M19/K01 Erisilebilirlik Kaliplari) const kacirilan = KK4 * lidersizPay, cift = KK4 * ikiLiderliPay; console.log(`${String(KK4).padStart(5)}${kacirilan.toFixed(2).padStart(21)}` + `${(kacirilan * FATURA_SATIRI).toFixed(0).padStart(19)}${cift.toFixed(2).padStart(16)}` + `${(cift * FATURA_SATIRI).toFixed(0).padStart(12)}`); } console.log(`\ncitleme + kalici tetik ile: kacirilan parti ${c.kacirilan}, ` + `cift baslatilan parti ${c.ciftBaslatma}, gecikmeli baslama ${c.gecikmeliTur} tur`); console.log(`kira 8 (uzun) ile: devralma turu ${kosum({ kira: 8 }).devralmaTuru}, ` + `lidersiz tur ${kosum({ kira: 8 }).lidersizTur}, iki liderli tur ${kosum({ kira: 8 }).ikiLiderliTur}`);
model penceresi: lidersiz 2/24 = 0.0833, iki liderli 2/24 = 0.0833
bir parti = 4000 fatura satiri (K01, hesap)
KK4 kacirilan parti/yil uretilmeyen satir cift parti/yil cift satir
6 0.50 2000 0.50 2000
12 1.00 4000 1.00 4000
citleme + kalici tetik ile: kacirilan parti 0, cift baslatilan parti 0, gecikmeli baslama 2 tur
kira 8 (uzun) ile: devralma turu 0, lidersiz tur 5, iki liderli tur 0
Yılda altı devralmada beklenen kaçırılan parti 0,50 ve beklenen çift parti 0,50’dir. Sayıyı fatura satırına çevirdiğinizde iki yılda bir 4000 satırlık bir gün hiç üretilmez ve iki yılda bir 4000 satır iki kez üretilir; yıllık beklenti her ikisinde de 2000 satırdır. Devralma sayısı ikiye katlanırsa yılda birer olay ve 4000’er satır olur.
Bu sayıların büyüklüğü kararın nereye bağlanacağını söylüyor. Hizmet erişilebilirliği cinsinden bakıldığında iki tur lidersizlik hiçbir şeydir; K01’in kesinti bütçesinde görünmez. Fatura satırı cinsinden bakıldığında aynı iki tur, yılda 2000 çift satır demektir ve her biri bir satıcıya yanlış tutar yansıtır. Tekil sorumluluk gerektiren işlerde ölçünün birimi süre değil, iştir. Çitleme çift satırı sıfıra indirir, kalıcı tetik üretilmeyen satırı sıfıra indirir; ikisi birlikte iki turluk bir gecikmeye mal olur. Lider seçimi tek başına bu iki hatanın hiçbirini kaldırmaz.
Özet
- Lider seçimi ile hizmeti sürdüren devralma ayrı sorulardır: birinde amaç yazma kabul eden bir kopyanın kalması, ötekinde işin yalnız bir kez yapılmasıdır.
- Kira süresi düşen düğümü değil yazamayan düğümü ayırt eder; duraklamış lider geri döndüğünde kendini hâlâ lider sanar.
- Yalın koşumda 4 tetikten 3’ü başlatıldı: 1 parti kaçtı (lidersiz turda geldi), 1 parti iki kez başlatıldı (iki liderli turda geldi), devralma 3 turda tamamlandı.
- Çitleme inancı değil etkiyi düzeltir: iki liderli tur 2’de kalırken çift başlatılan parti 1’den 0’a indi, reddedilen iş 0’dan 2’ye çıktı. Kalıcı tetik kaçırılan partiyi 0’a indirdi ve iki turluk gecikme getirdi.
- Kira uzadıkça devralma 2’den 5 tura, lidersiz tur 1’den 4’e çıkıyor; iki liderli pencere ise değişmiyor, çünkü kaynağı kira değil geri dönen düğümün kaydı yeniden okuma anıdır.
- K01’e dönüş: KK4 = yılda 6 devralma ile beklenen kaçırılan parti 0,50 ve çift parti 0,50, yani yılda 2000 üretilmeyen ve 2000 çift fatura satırı; devralma 12’ye çıkarsa 4000’er olur.
Sonraki Adım
Bu kursun bütün derslerinde iş, isteği yapan taraftan koparılmış olarak yürüdü: durum olayı kuyruğa yazıldı, iş akışı arkada koştu, gün sonu partisi bir lider tarafından başlatıldı. Bir soru hep dışarıda kaldı — isteyen tarafın sonucu nasıl öğrendiği. Bir satıcı otuz günlük ücretlendirme raporunu istediğinde, iş kuyruğa alınır ve saniyeler sonra biter; ama satıcının tarayıcısı bir yanıt bekliyordur ve bağlantı o kadar açık tutulamaz. Sonraki ders bu boşluğu kapatan yerleşimi kurar: isteğin hemen bir iş kimliğiyle karşılanması, sonucun ayrı bir adresten alınması ve istemcinin sonucu görene kadar kaç kez sorduğunun ölçülmesi.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.