İçeriğe geç
academia.sh

Ders 17 / 19

Tutarlılık Modelleri

Ayar bileşimlerinin tutarlılık modeline çevrilmesi: hangi okuma ve yazma ilgisinin hangi modeli verdiğinin aynı üye oturumunun altı ayarda koşturulmasıyla ölçülmesi, oturum güvencelerinin korunduğu ayarların kendi yazdığını okuyamama ve monotonik ihlal sayılarıyla ayrılması, ayrı parçalarda duran iki derlem üzerinde nedensel tutarlılığın tanımlanması ve nedensel bağı kopan okumaların sayılması, her güvencenin bedelinin beklenen tur sayısına çevrilmesi.

İçindekiler

Önceki dersin iki tablosu ayarları saydı ama adlarını koymadı. w=1 ile yerel okumanın verdiği söz ile w=çoğunluk ile çoğunluk okumasının verdiği söz aynı değildir; ikisinin arasında duran bileşimler de ayrı şeyler vaat eder. Bu sözlerin adları — güçlü tutarlılık, sonunda tutarlılık, monotonik okuma, kendi yazdığını okuma — Sistem Tasarımına Giriş kursunda tanımlandı ve orada ölçüldü. Tanımlar burada tekrarlanmaz.

Bu dersin işi çeviridir. Depoda bir tutarlılık modeli seçilmez; bir ayar seçilir. Yazma ilgisi, okuma ilgisi ve okuma yönünden oluşan üçlü bir model adına karşılık gelir ve o adı hak edip etmediği sayılabilir. Ders o eşlemeyi kurar, listede bulunmayan bir modeli — nedensel tutarlılığı — ekler ve aynı üye oturumunu altı ayarda koşturur.

Nedensel Tutarlılık

Sonunda tutarlılık ile güçlü tutarlılık arasında geniş bir aralık vardır ve o aralığın en kullanışlı noktası nedensel tutarlılıktır (causal consistency). Sözü şudur: bir yazma başka bir yazmanın sonucu görülerek yapılmışsa, ikincisini gören her okuma birincisini de görür. Aralarında bağ olmayan yazmalar farklı sıralarla görülebilir. Güçlü tutarlılıktan ayrıldığı yer budur: bütün yazmaları tek sıraya dizmez, yalnız bağlı olanları dizer.

Kütüphane veritabanında bağ somuttur. Bir ödünç kaydı yazılır; kayıt onaylandıktan sonra o ödünce ait gecikme cezası yazılır. Ceza kaydı ödünç kaydına atıf yapar ve ancak onun varlığı görüldüğü için üretilmiştir. Bağın kopması tek bir okumadır: ceza görünüyor, atıf yaptığı ödünç kaydı görünmüyor. Ekranda kaynağı bulunamayan bir ceza kalır.

Tek bir çoğaltma kümesinde bu olamaz, çünkü ikincil birincilin günlüğünü sırayla uygular: ceza kaydını uygulamış bir üye ödünç kaydını da uygulamıştır. Kopma, iki derlemin ayrı parçalarda durmasıyla gelir. Önceki iki ders bu düzeni kurdu — parça anahtarı derlem başına seçilir ve her parça kendi çoğaltma kümesidir. İki kümenin üye uzaklıkları birbirinden bağımsızdır ve okuyan oturum iki derlemi iki ayrı üyeden okur. Sıra güvencesi kümenin içindedir, kümeler arasında değil.

Düzenek

Düzenek yine bir modeldir: gerçek küme kurulmaz, tur soyut bir adımdır, üye uzaklığı tur cinsinden bir parametredir.

NS21 — ceza parçasının çoğaltma kümesinde üye uzaklıkları 1, 2, 3 ve 4 turdur; ödünç parçasının kümesi NS19’un kümesidir (3, 5, 6, 8 tur). Gerekçe: ceza derlemi tek yerleşkede tutulur, ödünç derlemi şubelere yayılmıştır. NS22 — sekiz turda bir ödünç işlemi yapılır ve ceza kaydı, ödünç kaydının onayından bir tur sonra gönderilir. Gerekçe: ceza, kaydın işlendiği görüldükten sonra yazılır. İki varsayım da doğrusal etkilidir: uzaklıklar büyürse kopma penceresi aynı oranda büyür.

// oturum/model.mjs — oturum guvenceleri ve nedensellik MODELIDIR: tur soyut bir adimdir, uye
// uzakligi tur cinsinden bir parametredir, gercek kume kurulmaz. Odunc derlemi ile ceza derlemi
// AYRI PARCALARDA durur; her parca kendi cogaltma kumesidir ve uzakliklari ayridir. Ceza kaydi,
// odunc kaydi ONAYLANDIKTAN sonra gonderilir: iki yazma arasindaki bag nedenseldir.
export const GECIKME = { odunc: [0, 3, 5, 6, 8], ceza: [0, 1, 2, 3, 4] };
export const ISLEM = 12, ARALIK = 8, TUR = 108, COGUNLUK = 3, IKINCIL = [1, 2, 3, 4];

// 03. dersin turetimi: onay turu, ikincillerin uzaklik siralamasindaki (w-1). degerin iki kati
export const onayTuru = (parca, w) =>
  w <= 1 ? 0 : 2 * GECIKME[parca].slice(1).sort((a, b) => a - b)[w - 2];

// Bir uyenin t turunda gordugu en buyuk sira. Cogunluk okumasi ayrica cogunluga ulasmis ve
// birincilin bunu ogrendigi noktayla sinirlidir (03. dersteki taahhut noktasi).
const gorunen = (yazma, parca, uye, t, okuma) => yazma.reduce((s, y) =>
  y.gonderim + GECIKME[parca][uye] <= t
  && (okuma !== "cogunluk" || y.gonderim + onayTuru(parca, COGUNLUK) <= t) ? y.sira : s, 0);

// "birincil" tek uye; "yapiskan" oturumu iki parcada da en yakin ikincile baglar; "donusumlu"
// her turda baska bir ikincile gider ve iki parcayi ters yonde dolasir. Dort turda bir, odunc
// okumasi en yakin ikincilden en uzagina atlar: monotonik ihlalin gorunecegi yer orasidir.
const uyeSec = (yon, t, parca) => yon === "birincil" ? 0 : yon === "yapiskan" ? IKINCIL[0]
  : parca === "ceza" ? IKINCIL[t % 4] : IKINCIL[(3 * t) % 4];

export function kosum({ w, okuma = "yerel", yon = "birincil", belirtec = false }) {
  const onay = onayTuru("odunc", w), odunc = [], ceza = [];
  for (let j = 1; j <= ISLEM; j += 1) {            // odunc takvimi ayardan bagimsizdir
    const g = 1 + (j - 1) * ARALIK;
    odunc.push({ sira: j, gonderim: g, onay: g + onay });
    ceza.push({ sira: j, gonderim: g + onay + 1 });
  }
  const oku = (y, p, u, t) => gorunen(y, p, u, t, okuma);
  // Oturum belirteci acikken okuma, hedefe ulasmamis uyeden yanitlanmaz: uye yetisene kadar
  // beklenir. Beklenen tur sayisi guvencenin bedelidir.
  const yetis = (y, p, u, t, hedef) => {
    let x = t;
    while (x <= TUR && oku(y, p, u, x) < hedef) x += 1;
    return x - t;
  };

  let kyo = 0, yazmaBekleme = 0;                   // yazan oturum: onay turunda kaydi geri okur
  for (const y of odunc) {
    const t = y.onay, u = uyeSec(yon, t, "odunc");
    if (oku(odunc, "odunc", u, t) >= y.sira) continue;
    if (belirtec) yazmaBekleme += yetis(odunc, "odunc", u, t, y.sira); else kyo += 1;
  }

  // okuyan oturum: her turda once ceza derlemi, sonra cezanin atif yaptigi odunc kaydi okunur
  let mono = 0, kopma = 0, bayat = 0, okumaBekleme = 0, beklemeli = 0, gorulenSira = 0;
  for (let t = 1; t <= TUR; t += 1) {
    const gc = oku(ceza, "ceza", uyeSec(yon, t, "ceza"), t);
    const u = uyeSec(yon, t, "odunc");
    let go = oku(odunc, "odunc", u, t), tr = t;    // tr: yanitin verildigi tur
    if (belirtec) {
      const b = yetis(odunc, "odunc", u, t, Math.max(gc, gorulenSira));
      if (b > 0) { beklemeli += 1; okumaBekleme += b; tr = t + b; go = oku(odunc, "odunc", u, tr); }
    }
    if (go < gorulenSira) mono += 1;
    if (gc > go) kopma += 1;                       // ceza gorunuyor, atif yaptigi odunc gorunmuyor
    if (go < odunc.filter((y) => y.onay <= tr).length) bayat += 1;  // yanit aninda onaylanmisa gore
    gorulenSira = Math.max(gorulenSira, go);
  }
  return { kyo, mono, kopma, bayat, bekleme: yazmaBekleme + okumaBekleme,
    yazmaBekleme, okumaBekleme, beklemeli, onay };
}
// oturum/olc.mjs — ayni uye oturumu alti ayarda: hangi ayar hangi guvenceyi veriyor
import { kosum, onayTuru, GECIKME, IKINCIL, ISLEM, ARALIK, TUR, COGUNLUK } from "./model.mjs";

const s = (x, n) => String(x).padStart(n);
const AYAR = [
  ["w=1 / yerel / donusumlu", { w: 1, yon: "donusumlu" }],
  ["w=1 / yerel / yapiskan", { w: 1, yon: "yapiskan" }],
  ["w=1 / yerel / donusumlu + belirtec", { w: 1, yon: "donusumlu", belirtec: true }],
  ["w=1 / yerel / birincil", { w: 1, yon: "birincil" }],
  ["w=cogunluk / cogunluk / birincil", { w: COGUNLUK, okuma: "cogunluk", yon: "birincil" }],
  ["w=cogunluk / cogunluk / donusumlu", { w: COGUNLUK, okuma: "cogunluk", yon: "donusumlu" }],
];
console.log(`odunc parcasinin uye uzakliklari ${GECIKME.odunc.join("/")}, ceza parcasininki ` +
  `${GECIKME.ceza.join("/")} tur.\n${TUR} tur, ${ARALIK} turda bir odunc kaydi (${ISLEM} islem); ` +
  `ceza kaydi kendi odunc kaydinin\nonayindan bir tur sonra gonderilir.\n`);
console.log("ayar (yazma ilgisi / okuma ilgisi / yon) | kendi yazdigini | monotonik | nedensel | bayat  | onay | bekleme");
console.log("                                         |    okuyamama    |   ihlal   |  kopma   | okuma  | turu |  (tur)");
console.log("-----------------------------------------|-----------------|-----------|----------|--------|------|--------");
for (const [ad, secim] of AYAR) {
  const r = kosum(secim);
  console.log(`${ad.padEnd(40)} | ${s(`${r.kyo}/${ISLEM}`, 15)} | ${s(r.mono, 9)} | ` +
    `${s(`${r.kopma}/${TUR}`, 8)} | ${s(`${r.bayat}/${TUR}`, 6)} | ${s(r.onay, 4)} | ${s(r.bekleme, 7)}`);
}
const b = kosum({ w: 1, yon: "donusumlu", belirtec: true });
console.log(`\nbelirtecli ayarda bekleme: ${b.yazmaBekleme} tur ${ISLEM} geri okumada, ` +
  `${b.okumaBekleme} tur okuyan oturumda\n(${b.beklemeli}/${TUR} okuma bekledi).`);

// Kosumdan bagimsiz: ceza gorunup odunc gorunmemesi, ancak odunc uyesinin uzakligi ceza
// uyesinin uzakligindan iki yazma arasindaki bosluktan (onay turu + 1) fazla buyukse olur.
for (const w of [1, COGUNLUK]) {
  const bosluk = onayTuru("odunc", w) + 1;
  const n = IKINCIL.flatMap((uo) => IKINCIL.map((uc) =>
    GECIKME.odunc[uo] > GECIKME.ceza[uc] + bosluk)).filter(Boolean).length;
  console.log(`kosumdan bagimsiz: iki yazma arasindaki bosluk w=${w === 1 ? "1" : "cogunluk"} ` +
    `ayarinda ${bosluk} tur;\n${IKINCIL.length ** 2} uye ciftinin ${n} tanesinde kopma, ` +
    `yonlendirme hangisi olursa olsun kacinilmazdir.`);
}
const enUzak = Math.max(...GECIKME.odunc), oc = onayTuru("odunc", COGUNLUK);
console.log(`kosumdan bagimsiz: en buyuk uye uzakligi ${enUzak} tur, cogunluk onay turu ${oc} tur;` +
  `\n${enUzak} < ${oc} oldugu icin cogunluk okumasinin dondurdugu deger okunan uyeden bagimsizdir.`);
odunc parcasinin uye uzakliklari 0/3/5/6/8, ceza parcasininki 0/1/2/3/4 tur.
108 tur, 8 turda bir odunc kaydi (12 islem); ceza kaydi kendi odunc kaydinin
onayindan bir tur sonra gonderilir.

ayar (yazma ilgisi / okuma ilgisi / yon) | kendi yazdigini | monotonik | nedensel | bayat  | onay | bekleme
                                         |    okuyamama    |   ihlal   |  kopma   | okuma  | turu |  (tur)
-----------------------------------------|-----------------|-----------|----------|--------|------|--------
w=1 / yerel / donusumlu                  |           12/12 |        24 |   24/108 | 60/108 |    0 |       0
w=1 / yerel / yapiskan                   |           12/12 |         0 |   12/108 | 36/108 |    0 |       0
w=1 / yerel / donusumlu + belirtec       |            0/12 |         0 |    0/108 | 47/108 |    0 |     156
w=1 / yerel / birincil                   |            0/12 |         0 |    0/108 |  0/108 |    0 |       0
w=cogunluk / cogunluk / birincil         |            0/12 |         0 |    0/108 |  0/108 |   10 |       0
w=cogunluk / cogunluk / donusumlu        |            0/12 |         0 |    0/108 |  0/108 |   10 |       0

belirtecli ayarda bekleme: 96 tur 12 geri okumada, 60 tur okuyan oturumda
(24/108 okuma bekledi).
kosumdan bagimsiz: iki yazma arasindaki bosluk w=1 ayarinda 1 tur;
16 uye ciftinin 12 tanesinde kopma, yonlendirme hangisi olursa olsun kacinilmazdir.
kosumdan bagimsiz: iki yazma arasindaki bosluk w=cogunluk ayarinda 11 tur;
16 uye ciftinin 0 tanesinde kopma, yonlendirme hangisi olursa olsun kacinilmazdir.
kosumdan bagimsiz: en buyuk uye uzakligi 8 tur, cogunluk onay turu 10 tur;
8 < 10 oldugu icin cogunluk okumasinin dondurdugu deger okunan uyeden bagimsizdir.

Oturum Güvenceleri Hangi Ayarda Korunur

İlk satırda ödünç masası kendi yazdığını hiç okuyamıyor: 12 onaylı yazmanın 12’si, onay geldiği turda yapılan geri okumada bulunamadı. Bu sayı koşuma bağlı değildir. w=1 ayarında onay turu 0’dır, en yakın ikincil ise 3 tur geridedir; ikincile giden bir geri okuma kaydı hiçbir koşumda bulamaz. Ödünç ekranında bunun karşılığı, kitap verildikten hemen sonra üyenin ödünç listesinin boş görünmesidir.

Aynı satırda 24 monotonik ihlal var. Sebep yönlendirmenin dönüşümlü olmasıdır: okuma dört turda bir en yakın ikincilden en uzağına atlıyor ve o üye aradaki yazmayı henüz uygulamamış oluyor. Ekranda görünen ödünç sayısı geri gidiyor.

İkinci satır, Önbellekleme, Kuyruklar ve Eşzamansız İşleme kursunun yapışkan yönlendirmesini okuma yoluna uyguluyor: oturum tek bir ikincile bağlanıyor. Monotonik ihlal 24’ten 0’a iniyor, çünkü bir üyenin sıra numarası hiç geri gitmez; bayat okuma da 60’tan 36’ya iniyor. Değişmeyen tek sütun kendi yazdığını okuyamamadır: hâlâ 12/12. Yapışkanlık istemciyi bir ikincile bağlar, o ikincil de birincilin gerisindedir.

Dördüncü satır iki oturum güvencesini de bedelsiz veriyor: 0/12, 0 ihlal, 0 bayat okuma, 0 tur bekleme. Oturum güvencelerinin en ucuz yolu okuma yönünü birincile çekmektir. Bu ayarın bedeli bu tabloda görünmez; önceki ders ölçtü — arıza penceresinde 3 yanıtsız istek ve sonradan geri alınacak veriyi gören 3 okuma.

Nedensel Bağın Kopması

Nedensel kopma sütunu, oturum güvencelerinin yetmediği yeri gösteriyor. Dönüşümlü ayarda 108 okumanın 24’ünde ceza göründü, atıf yaptığı ödünç kaydı görünmedi. Yapışkan ayarda bu sayı 12’ye indi ama sıfırlanmadı — oysa aynı satırda monotonik ihlal 0. İki sütunun ayrışması bu dersin ana sonucudur: yapışkan yönlendirme oturumu bir üyeye bağlar ve o üyenin içindeki sırayı korur; iki ayrı parçanın iki ayrı kümesi arasındaki bağı korumaz. Ceza parçasının en yakın ikincili 1 tur, ödünç parçasınınki 3 tur geridedir ve ceza yazması ödüncün onayından yalnız 1 tur sonra gönderilir; aradaki iki turluk fark her işlemde bir kopma üretir.

Üçüncü satır bağı kapatan ayarı gösteriyor. Oturum, gördüğü en ileri noktayı bir oturum belirtecinde taşır; okuma, o noktanın gerisinde kalan bir üyeden yanıtlanmaz, üye yetişene kadar beklenir. Üç ihlal sütunu da 0’a iniyor. Bedel bekleme sütunundadır: 156 tur — 96’sı 12 geri okumada, 60’ı okuyan oturumda, 108 okumanın 24’ü bekleyerek.

Aynı satırın bayat okuma sütunu 47/108 kalıyor ve bu bir kusur değil, tanımın kendisidir. Nedensel tutarlılık yanıtın geri gitmeyeceğini söyler, en güncel olacağını değil.

Son iki koşumdan bağımsız satır kopmanın yapısını veriyor. Kopma, ödünç üyesinin uzaklığı ceza üyesinin uzaklığından iki yazma arasındaki boşluktan fazla büyükse olur. w=1 ayarında bu boşluk 1 turdur ve 16 üye çiftinin 12’sinde kopma, hangi yönlendirme seçilirse seçilsin kaçınılmazdır. w=çoğunluk ayarında boşluk 11 tura çıkar ve kopmalı çift sayısı 0 olur. Onay düzeyini yükseltmek kopma olasılığını azaltmaz; kopmayı yapısal olarak ortadan kaldırır.

Ayarın Model Adına Çevrilmesi

Ayar Verdiği model Ölçülen karşılığı
w=1, yerel, dönüşümlü ikincil sonunda tutarlılık 12/12 okuyamama, 24 ihlal, 24/108 kopma
w=1, yerel, yapışkan ikincil sonunda tutarlılık ve monotonik okuma 0 ihlal, kopma 12/108 sürüyor
w=1, yerel, oturum belirteci nedensel tutarlılık üç ihlal de 0, 156 tur bekleme, 47/108 bayat
w=çoğunluk, çoğunluk güçlü tutarlılık bütün sütunlar 0, yazma başına 10 tur onay

Son iki satır aynı sayıları veriyor: çoğunluk okuması birincilden de dönüşümlü ikincillerden de aynı değeri döndürüyor. Sebep koşumdan bağımsızdır — en büyük üye uzaklığı 8 tur, çoğunluk onay turu 10 turdur ve 8 < 10 olduğu için hiçbir üye taahhüt noktasının gerisinde kalamaz. Uzak bir yerleşkeye 12 tur ötede bir üye eklenirse bu eşitsizlik bozulur ve çoğunluk okuması da hangi üyeden okunduğuna bağlı hâle gelir.

Dördüncü ve beşinci satırın ayırt edilememesi tablonun sınırıdır, ayarların değil. Küme sağlamken birincil ile yerel bileşimi güçlü tutarlılığın bütün sıfırlarını bedava veriyor. Farkı önceki ders ölçtü: birincil düştüğünde w=1 ayarında 3 kayıp yazma çıktı, w=çoğunluk ayarında 0. Yazma başına 10 turluk onay o farkın fiyatıdır.

Özet

  • Depoda tutarlılık modeli seçilmez, ayar seçilir: yazma ilgisi, okuma ilgisi ve okuma yönü üçlüsü bir model adına karşılık gelir ve o adı hak edip etmediği sayılabilir.
  • w=1 ile ikincilden okuyan her ayarda kendi yazdığını okuyamama 12/12 çıktı; bu koşuma bağlı değildir, çünkü onay turu 0 iken en yakın ikincil 3 tur geridedir.
  • Yapışkan yönlendirme monotonik ihlali 24’ten 0’a indirdi ama nedensel kopmayı 24’ten yalnız 12’ye: oturum güvencesi bir üyenin içindeki sırayı korur, iki parçanın kümeleri arasındaki bağı korumaz.
  • Nedensel tutarlılık bir oturum belirteciyle sağlandı; üç ihlal sütunu da 0’a indi, bedeli 156 tur bekleme oldu ve bayat okuma 47/108 kaldı.
  • Onay düzeyini çoğunluğa çekmek iki yazma arasındaki boşluğu 1 turdan 11 tura çıkardı ve kopmalı üye çifti sayısını 12’den 0’a indirdi; bu, olasılık değil yapı değişikliğidir.
  • Sağlam kümede birincil ile yerel bileşimi güçlü tutarlılıkla aynı sıfırları bedelsiz verdi; fark ancak arıza penceresinde görünür ve fiyatı yazma başına 10 turdur.

Sonraki Adım

Buraya kadarki ölçümler kümenin bütün olduğunu varsaydı: üyeler birbirini görüyor, değişen tek şey gecikmeydi. Bağ koptuğunda aynı ayarların anlamı değişir: w=çoğunluk çoğunluğu toplayamayan tarafta yazmayı durdurur, yerel okuma yanıt vermeyi sürdürür. Bu ödünleşim Sistem Tasarımına Giriş kursunda CAP ve PACELC adlarıyla kurulup ölçüldü. Depo bağlamında ise ödünleşim yanlış ifade edilir: bir deponun “CP” ya da “AP” olduğu söylenir, bir ürün özelliğiymiş gibi. Sonraki ders bu ifadeyi düzeltir: aynı küme aynı bölünmede birden çok ayarla koşturulur ve etiketin deponun değil ayarın özelliği olduğu sayılır. Bu derste ölçülen 10 turluk onay küme sağlamken de ödenir; bölünme dışındaki fatura odur.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat