Ders 12 / 13
Tutarlılık Modelleri
Güçlü, zayıf ve sonunda tutarlılığın ayrılması: dağıtık tutarlılığın işlem yalıtımından farklı bir soru olduğunun söylenmesi, aynı olay dizisinin üç modelle okunup iki istemcinin farklı değer görme sayısının, yakınsama için gereken tur sayısının ve monotonik okuma ihlallerinin ölçülmesi, yapışkan yönlendirmenin monotonik okumayı düzeltirken istemciler arası farkı büyütmesinin gösterilmesi.
İçindekiler
Önceki ders eskilik penceresini tek bir sayıya indirdi: 0 ya da D tur. Bu sayı bir pencerenin
genişliğidir, içinde ne olabileceğini söylemez. Aynı D turluk pencerede iki istemci aynı
gönderiyi sorup farklı durum görebilir; bir istemci ilerleyen bir dizi yerine geri giden bir dizi
görebilir; üçüncü bir istemci kendi yazdığı olayı sonraki sorgusunda bulamayabilir. Bunlar ayrı
olgulardır ve hiçbiri ötekinin yerine geçmez.
Pencerenin içini tanımlayan şeye tutarlılık modeli denir: sistemin okumalar hakkında ne söz verdiği. Bu ders üç modeli adlandırır ve aynı olay dizisini üçüyle okuyup sözlerin farkını sayar.
Model, Yalıtım Düzeyi Değildir
Tutarlılık sözcüğü depoda iki ayrı yerde geçti. Veri Modelleme ve İlişkisel Kuram kursunda ACID özelliklerinden biri, İleri SQL kursunda yalıtım düzeylerinin ölçütüydü. Buradaki soru başkadır ve ikisi birbirinin yerine geçmez: işlem yalıtımı eşzamanlı işlemlerin birbirinin yarım işini görüp görmediğini düzenler, dağıtık tutarlılık ise onaylanmış bir yazmanın kopyalar arasında ne zaman görünür olduğunu düzenler. Bir sistem en katı yalıtım düzeyini uygularken sonunda tutarlı olabilir; ikisi ayrı ayrı seçilir. Yalıtım düzeyleri bu derste yeniden anlatılmaz.
Çoğaltmanın nasıl yürüdüğü de İlişkisel Veritabanı Yönetimi kursunda kuruldu. Burada ölçülen, aynı çoğaltmanın üstüne konan sözün ne olduğudur.
Üç Model
Güçlü tutarlılık: her okuma, en son onaylanmış yazmayı görür. Sistem dışarıdan tek kopyalı görünür. Bedeli, yerel kopyanın elindeki değerin en yeni olduğunu doğrulamasıdır.
Sonunda tutarlılık (eventual consistency): okuma en son yazmayı görmeyebilir, ancak yazma durduğunda bütün kopyaların aynı değere yakınsayacağı güvence altındadır. Terim Veri Modelleme ve İlişkisel Kuram kursunda tanıtıldı; buradaki ekleme, yakınsamanın kendiliğinden olmadığıdır — kaybolan bir yayılımın yeniden gönderilmesini sağlayan bir onarım mekanizması gerekir.
Zayıf tutarlılık: hiçbir söz verilmez. Okuma eski değer görebilir ve kopyalar hiç yakınsamayabilir. Bu, sonunda tutarlılığın gevşek bir hâli değildir; yakınsama güvencesinin yokluğudur ve aradaki fark ölçülebilir.
Üç Kopyalı Düzenek
Model üç bölgeli bir kopya kümesi kurar. Yazmalar b34 bölgesine gelir ve b35 ile b06
bölgelerine yayılır; yayılım gecikmeleri ve bir kayıp kuralı model parametreleridir. İki istemci
her turda aynı takip numarasını okur ve sırayla farklı bölgelere yönlenir.
// tutarlilik/model.mjs — uc kopyali surec ici model. Tur soyut bir adimdir; gecikme, kayip // kurali ve onarim araligi model parametreleridir, olculmus sureler degildir. const GECIKME = { b35: 1, b06: 3 }; // yayilimin hedefe varmasi icin gecen tur const KAYIP = (yazma) => yazma % 5 === 0; // b06'ya giden yayilim bu yazmalarda kaybolur const ONARIM = 2; // onarimli modellerde yeniden gonderme araligi const YOL = { A: ["b34", "b35", "b06"], B: ["b06", "b35", "b34"] }; const SABIT = { A: ["b35"], B: ["b06"] }; // yapiskan yonlendirme: istemci tek kopyada kalir export function kosum({ tur: N, yazmaSonu: W, model, sabit = false }) { const surum = { b34: 0, b35: 0, b06: 0 }; const gorulen = { A: 0, B: 0 }; const iz = { A: [], B: [] }; let ucus = [], ileti = 0, farkli = 0, ihlal = 0, yakinsama = null; for (let tur = 1; tur <= N; tur++) { if (tur <= W) { surum.b34 = tur; // tasiyici olayi b34'e yazilir, tasiyiciya hemen onay verilir for (const h of ["b35", "b06"]) { ileti += 1; ucus.push({ hedef: h, yazma: tur, varir: tur + GECIKME[h], kayip: h === "b06" && KAYIP(tur) }); } } const varan = ucus.filter((m) => m.varir === tur); ucus = ucus.filter((m) => m.varir !== tur); for (const m of varan) { if (m.kayip === false) { surum[m.hedef] = Math.max(surum[m.hedef], m.yazma); continue; } if (model === "zayif") continue; // kayip onarilmaz: yakinsama guvencesi yoktur ileti += 1; ucus.push({ ...m, varir: tur + ONARIM, kayip: false }); } const oku = (istemci) => { const yol = sabit ? SABIT[istemci] : YOL[istemci]; const bolge = yol[(tur - 1) % yol.length]; if (model !== "guclu") return surum[bolge]; if (bolge !== "b34") ileti += 2; // yerel kopya, en son yazmayi b34'e dogrulatir return surum.b34; }; const deger = { A: oku("A"), B: oku("B") }; if (deger.A !== deger.B) farkli += 1; for (const i of ["A", "B"]) { if (deger[i] < gorulen[i]) ihlal += 1; gorulen[i] = Math.max(gorulen[i], deger[i]); iz[i].push(deger[i]); } if (tur > W && yakinsama === null && surum.b34 === surum.b35 && surum.b35 === surum.b06) { yakinsama = tur - W; } } return { farkli, ihlal, ileti, yakinsama, surum, iz }; }
Üç modelin kodda ayrıldığı yer iki satırdır: kayıp bir yayılımın yeniden gönderilip
gönderilmediği ve okumanın b34’e doğrulatılıp doğrulatılmadığı. Monotonik okuma ihlali,
bir istemcinin daha önce gördüğü bir sürümden eski bir sürüm görmesidir.
// tutarlilik/olc.mjs — ayni olay dizisi uc modelle okunur: fark, ihlal, yakinsama, ileti import { kosum } from "./model.mjs"; const TUR = 20, YAZMA_SONU = 10; const s = (x, n) => String(x).padStart(n); console.log(`${TUR} tur, ${YAZMA_SONU}. tura kadar her turda bir yazma; sonra yazma yok.`); console.log("iki istemci her turda ayni takip numarasini okur, farkli kopyalara yonlenir."); console.log(); console.log("model | farkli deger | monotonik ihlal | yakinsama | ileti | son surum b34/b35/b06"); console.log("--------------|--------------|-----------------|-------------|-------|----------------------"); const DUZEN = [["guclu", false], ["sonunda", false], ["sonunda", true], ["zayif", false]]; const kayit = {}; for (const [model, sabit] of DUZEN) { const r = kosum({ tur: TUR, yazmaSonu: YAZMA_SONU, model, sabit }); const ad = sabit ? `${model}+sabit` : model; kayit[ad] = r; console.log(`${ad.padEnd(13)} | ${s(`${r.farkli}/${TUR}`, 12)} | ${s(r.ihlal, 15)} | ` + `${s(r.yakinsama === null ? "yakinsamadi" : `${r.yakinsama} tur`, 11)} | ${s(r.ileti, 5)} | ` + `${r.surum.b34}/${r.surum.b35}/${r.surum.b06}`); } console.log(); for (const ad of Object.keys(kayit)) { console.log(`${ad.padEnd(13)} A: ${kayit[ad].iz.A.join(" ")}`); console.log(`${ad.padEnd(13)} B: ${kayit[ad].iz.B.join(" ")}`); }
node tutarlilik/olc.mjs
20 tur, 10. tura kadar her turda bir yazma; sonra yazma yok. iki istemci her turda ayni takip numarasini okur, farkli kopyalara yonlenir. model | farkli deger | monotonik ihlal | yakinsama | ileti | son surum b34/b35/b06 --------------|--------------|-----------------|-------------|-------|---------------------- guclu | 0/20 | 0 | 5 tur | 76 | 10/10/10 sonunda | 9/20 | 8 | 5 tur | 22 | 10/10/10 sonunda+sabit | 13/20 | 0 | 5 tur | 22 | 10/10/10 zayif | 13/20 | 12 | yakinsamadi | 20 | 10/10/9 guclu A: 1 2 3 4 5 6 7 8 9 10 10 10 10 10 10 10 10 10 10 10 guclu B: 1 2 3 4 5 6 7 8 9 10 10 10 10 10 10 10 10 10 10 10 sonunda A: 1 1 0 4 4 3 7 7 6 10 10 9 10 10 10 10 10 10 10 10 sonunda B: 0 1 3 1 4 6 4 7 9 7 10 10 9 10 10 10 10 10 10 10 sonunda+sabit A: 0 1 2 3 4 5 6 7 8 9 10 10 10 10 10 10 10 10 10 10 sonunda+sabit B: 0 0 0 1 2 3 4 4 6 7 8 9 9 9 10 10 10 10 10 10 zayif A: 1 1 0 4 4 3 7 7 6 10 10 9 10 10 9 10 10 9 10 10 zayif B: 0 1 3 1 4 6 4 7 9 7 10 10 9 10 10 9 10 10 9 10
Sayıların Okunması
guclu satırı sözün tam karşılığını veriyor: iki istemci hiçbir turda farklı değer görmedi
(0/20), monotonik ihlal 0 ve iki izin de tam olarak yazma dizisinin kendisi. Bedel ileti
sütununda: 76 ileti, en ucuz satırın yaklaşık dört katı. Bu ileti sayısının kaynağı okumadır,
yazma değil — yerel kopyaya düşen her okuma b34’e bir gidiş dönüş ekler. Bir okuma yoğun
akışta bedel okuma sayısıyla büyür.
sonunda satırı sözün sınırını gösteriyor. Yakınsama 5 tur: yazma bittikten beş tur sonra üç
kopya da 10 sürümünde birleşti. Yakınsama gerçekleşti ama pencere içinde 9 turda iki istemci
farklı değer gördü ve 8 monotonik ihlal oluştu. İzler bunu doğrudan gösteriyor: A istemcisi
1 1 0 ile başlıyor — üçüncü turda gönderinin durumunu hiç görmemiş gibi bir yanıt alıyor,
çünkü o tur b06 bölgesine yönlendi. Takip sorgusu için bu, ekranda görünen durumun geriye
gitmesi demektir.
zayif satırındaki tek fark bir mekanizmanın yokluğudur ve sonucu son sütunda görünür: kopyalar
10/10/9 durumunda kaldı, yakınsama hiç olmadı. Onuncu yazma b06‘ya giderken kaybolduğu ve
yeniden gönderilmediği için o bölge gönderiyi sonsuza kadar bir aşama geride gösterir. Yakınsama
güvencesinin bedeli ölçümde iki iletidir (20’ye karşı 22); sağladığı şey, kalıcı bir sapmanın
olmamasıdır. Sonunda tutarlılığı “hiçbir garanti vermeyen model” sanmak bu iki iletiyi görmemek
anlamına gelir.
Oturum Güvenceleri
Monotonik ihlal, tutarlılık modelinden ayrı bir eksende düzeltilebilir. sonunda+sabit satırında
model aynı kaldı; değişen tek şey istemcinin her turda aynı kopyaya yönlendirilmesidir —
Önbellekleme, Kuyruklar ve Eşzamansız İşleme kursunda tanıtılan yapışkan yönlendirme
kalıbının okuma yoluna uygulanmış hâli. İhlal 8’den 0’a
indi, çünkü bir kopyanın sürüm numarası hiç geri gitmez. Bu tür sözlere oturum güvencesi
denir; en bilinen ikisi monotonik okuma (bir istemci gördüğü değerden eskisini görmez) ve kendi
yazdığını okumadır (bir istemci kendi yazmasını sonraki okumasında görür).
Aynı satır ikinci ve daha önemli şeyi de söylüyor: farklı değer görme sayısı 9’dan 13’e
çıktı. Yapışkan yönlendirme istemciyi tek bir kopyaya bağlayınca A istemcisi hep b35’i, B istemcisi hep
b06’yı okur ve iki bölgenin gecikmesi farklı olduğu için ikisi neredeyse her turda ayrışır.
Oturum güvencesi bir istemcinin kendi gördüğü diziyi düzeltir; istemciler arasındaki farkı
düzeltmez, hatta büyütebilir.
Bu, gönderi takip servisinde iki ayrı gereksinime karşılık gelir. Bir kullanıcının aynı gönderiyi arka arkaya sorgulaması durumun geri gitmemesini gerektirir; yapışkan yönlendirme bunu sağlar. Gün sonu ücretlendirmesinin bütün gönderiler için aynı anı esas alması ise oturum güvencesiyle sağlanamaz — orada güçlü tutarlılık gerekir ve bedeli okuma başına bir gidiş dönüştür. Kursun sonraki dersinde bu iki gereksinim ayrı kalıplara bağlanacaktır.
Özet
- Dağıtık tutarlılık modeli, işlem yalıtımından ayrı bir sorudur: biri eşzamanlı işlemlerin birbirini görmesini, öteki onaylanmış bir yazmanın kopyalarda ne zaman göründüğünü düzenler.
- Aynı yirmi turluk olay dizisinde
guclumodel 0/20 farklı değer ve 0 ihlal üretti, bedeli 76 ileti oldu;sonundamodel 22 iletiyle 9/20 fark ve 8 ihlal üretti. - Sonunda tutarlılığın güvencesi yakınsamadır ve kendiliğinden gelmez: onarım mekanizması
kaldırıldığında (
zayif) kopyalar10/10/9durumunda kaldı ve hiç yakınsamadı; onarımın bedeli iki iletiydi. - Yakınsama 5 tur sürdü; bu süre boyunca söz yalnız “sonunda aynı olacak”tır, okumaların ne göreceği hakkında bir şey söylemez.
- Yapışkan yönlendirme monotonik ihlali 8’den 0’a indirdi ama iki istemcinin farklı değer görme sayısını 9’dan 13’e çıkardı; oturum güvencesi istemciler arası farkı düzeltmez.
Sonraki Adım
Buraya kadar üç dersin hepsi aynı örtük varsayımı taşıdı: kopyaların hepsi ayakta ve yalnız aralarındaki bağ ya da gecikme sorun çıkarıyor. Bir kopya tamamen düştüğünde soru değişir, çünkü artık yerine geçecek bir kopyanın bulunması, isteklerin oraya yönlendirilmesi ve bu geçiş sırasında düşen isteklerin hesaplanması gerekir. Geçişin nasıl düzenlendiği bir kalıp seçimidir: kopyaların biri yazma alırken ötekinin beklemesi ya da hepsinin aynı anda yazma alması. Sonraki ders bu iki kalıbı ölçer: etkin–pasif düzende devralma turu ile o sırada düşen istek sayısı, etkin–etkin düzende çakışan yazma sayısı ve çözüm kuralının ürettiği kayıp yazma sayısı.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.