Ders 09 / 14
Okuma Kopyaları
Kopya gecikmesinin uygulamaya nasıl yansıdığının ölçülmesi: 420.000 istekten oluşan bir akışta gecikme 0,1 saniyeden 5 saniyeye taranıp her değerde bayat okuma ve kendi yazdığını göremeyen istek sayısının çıkarılması, oturum tabanlı yapışkan pencerenin kaç isteği kurtardığı ile birincile kaydırdığı okuma payının karşılaştırılması, kopya sayısı arttıkça hem kopya başına kazancın hem de gecikmenin nasıl değiştiğinin sayılması ve bölge dışı kopyanın aylık aktarım bedelinin hesaplanması.
İçindekiler
Önceki ders tek birincil üzerinde durdu: ikinci makine beklemedeydi, devralma anına kadar hiçbir iş yapmıyordu. İş emri veritabanının istek karışımına bakıldığında bu israf göze batar — akışın büyük bölümü okumadır. Bekleyen kopyayı okumaya açmak yükü dağıtır ve yönetilen hizmette bu bir düğmedir.
Düğmenin altındaki şey devredilmiş bir karardır: çoğaltmanın nasıl işlediği artık görünmez. O mekanik — eşzamanlı mı eşzamansız mı, kaç üye onay veriyor — İleri Veri Ölçekleme kursunda ölçüldü ve burada tekrarlanmaz. Ölçülecek olan, mekaniğin dışarı sızan tek belirtisidir: kopya gecikmesi. Sayılacak olan da “gecikme kaç saniye” değil, gecikmenin kaç isteğe dokunduğudur.
İki Tür Bayat Okuma
Bayat okumaların hepsi aynı ağırlıkta değildir. Bir saha ekibi başka bir ekibin yarım saniye önce kapattığı iş emrini hâlâ açık görürse, bu bir tutarsızlıktır ama fark edilmez. Aynı ekip kendi kapattığı iş emrini listede hâlâ açık görürse, bu bir hatadır: ekran az önce yapılan işlemi yok saymıştır ve işlem ikinci kez denenir. Bu isteklere kendi yazdığını oku gereksinimi olan istekler denir ve ayrı sayılmaları gerekir, çünkü çözümleri de ayrıdır.
Düzenek
YV7 — akış 300 saniyelik bir penceredir: saniyede 1.400 istek, yüzde 78’i okuma (420.000 istek, 92.400 yazma). YV8 — kurgu ölçüm ağında 2.400 oturum ve 50.000 açık iş emri kaydı vardır; oturum bir saha ekibi ya da otomatik toplayıcıdır. YV9 — yazmaların yüzde 31’i, aynı oturum tarafından 120–900 ms sonra geri okunur; ekran işlemden sonra listeyi tazeler. YV10 — kopya gecikmesi tabanı 0,25 saniyedir ve her ek kopya 0,15 saniye ekler, çünkü çoğaltma akışı birincilden çekilir. YV11 — yük birimi kurgudur: yazma 1,0, okuma 0,4, kopya başına çoğaltma gönderimi yazmanın 0,08’i. YV12 — yönlendirme kuralı oturum tabanlıdır: bir oturum yazdıktan sonra W saniye boyunca okumaları birincile gider. YV9 doğrudan belirleyicidir; geri okuma aralığı büyürse ilk tablonun sağ sütunu aynı yönde küçülür.
// yv/model.mjs — okuma kopyasi MODELI. Kurgu bolgesel olcum aginin is emri istek akisi uretilir; // cogaltma MEKANIGI modellenmez (o M17/K05 ve M19/K04'te olculdu), yalnizca gecikmenin okumaya // nasil yansidigi olculur. Uretec kendi yazilmistir, tohum gorunurdur: her kosumda ayni akis. export const ISTEK = 1400, PENCERE = 300, OKUMA_PAYI = 0.78; export const OTURUM = 2400, VARLIK = 50000, GERI_OKUMA = 0.31; export const GERI_MIN = 0.12, GERI_MAX = 0.90; export function akisUret(tohum = 20260802) { let s = tohum % 2147483647; const rast = () => (s = (s * 48271) % 2147483647) / 2147483647; const toplam = ISTEK * PENCERE, yazmaSayisi = Math.round(toplam * (1 - OKUMA_PAYI)); const olay = []; for (let i = 0; i < yazmaSayisi; i += 1) { // is emri durum degisimi const t = rast() * PENCERE, o = Math.floor(rast() * OTURUM), e = Math.floor(rast() * VARLIK); olay.push([t, o, e, 1]); // 1 = yazma if (rast() < GERI_OKUMA) // ayni oturum kendi yazdigini okur olay.push([t + GERI_MIN + rast() * (GERI_MAX - GERI_MIN), o, e, 0]); } const kalan = toplam - olay.length; for (let i = 0; i < kalan; i += 1) // baskasinin verisini okuyanlar olay.push([rast() * PENCERE, Math.floor(rast() * OTURUM), Math.floor(rast() * VARLIK), 0]); olay.sort((a, b) => a[0] - b[0]); return olay; } // Her okuma icin uc sayi cikarilir: dw = o varliga en son yazmadan bu yana gecen sure (kopya bu // sureden kisa gecikmede geride kalir), kyo = son yazan oturum okuyanin kendisi mi, ds = okuyan // oturumun KENDI son yazmasindan bu yana gecen sure (yonlendirme kurali yalnizca bunu bilir). export function okumalariCikar(olay) { const sonYazma = new Map(), oturumSon = new Map(); const dw = [], kyo = [], ds = []; let yazma = 0; for (const [t, o, e, tur] of olay) { if (tur === 1) { sonYazma.set(e, [t, o]); oturumSon.set(o, t); yazma += 1; continue; } const y = sonYazma.get(e); dw.push(y ? t - y[0] : Infinity); kyo.push(y ? y[1] === o : false); ds.push(oturumSon.has(o) ? t - oturumSon.get(o) : Infinity); } return { dw, kyo, ds, yazma, okuma: dw.length }; } export const bayat = (r, L) => r.dw.reduce((n, d) => n + (d < L ? 1 : 0), 0); export const kyoBayat = (r, L) => r.dw.reduce((n, d, i) => n + (d < L && r.kyo[i] ? 1 : 0), 0); export const yonlenen = (r, W) => r.ds.reduce((n, d) => n + (d < W ? 1 : 0), 0); export const kurtarilan = (r, L, W) => r.dw.reduce((n, d, i) => n + (d < L && r.kyo[i] && r.ds[i] < W ? 1 : 0), 0); export const GECIKME_TABAN = 0.25, GECIKME_ARTIS = 0.15; export const YUK_YAZMA = 1.0, YUK_OKUMA = 0.4, YUK_COGALTMA = 0.08; export const gecikmeR = (R) => GECIKME_TABAN + GECIKME_ARTIS * R;
// yv/olc.mjs — kopya gecikmesinin uygulamaya yansimasi, yonlendirme kurali ve azalan getiri import { akisUret, okumalariCikar, bayat, kyoBayat, yonlenen, kurtarilan, gecikmeR, ISTEK, PENCERE, OTURUM, VARLIK, GERI_OKUMA, YUK_YAZMA, YUK_OKUMA, YUK_COGALTMA } from "./model.mjs"; const s = (x, n) => String(x).padStart(n); const y = (a, b) => "%" + (100 * a / b).toFixed(2); const r = okumalariCikar(akisUret()); console.log(`${ISTEK * PENCERE} istek / ${PENCERE} sn: ${r.yazma} yazma, ${r.okuma} okuma. ` + `${OTURUM} oturum, ${VARLIK} is emri. Tohum 20260802.`); console.log(`yazmalarin %${100 * GERI_OKUMA} kadari ayni oturum tarafindan geri okunur.\n`); console.log("kopya gecikmesi | bayat okuma | bayat pay | kendi yazdigini goremeyen | KYO pay"); console.log("----------------|-------------|-----------|---------------------------|---------"); for (const L of [0.1, 0.25, 0.5, 1, 2, 5]) { const b = bayat(r, L), k = kyoBayat(r, L); console.log(`${s(L.toFixed(2) + " sn", 15)} | ${s(b, 11)} | ${s(y(b, r.okuma), 9)} | ` + `${s(k, 25)} | ${s(y(k, r.okuma), 7)}`); } const L = 0.55; const taban = kyoBayat(r, L); console.log(`\nyonlendirme kurali, kopya gecikmesi ${L} sn sabit (${taban} istek kendi yazdigini goremiyor):`); console.log("yapiskan pencere W | birincile giden okuma | kurtarilan | kalan | birincile kayan okuma payi"); console.log("-------------------|-----------------------|------------|-------|---------------------------"); for (const W of [0, 0.25, 0.5, 1, 2, 5, 15]) { const g = yonlenen(r, W), k = kurtarilan(r, L, W); console.log(`${s(W.toFixed(2) + " sn", 18)} | ${s(g, 21)} | ${s(k, 10)} | ${s(taban - k, 5)} | ` + `${s(y(g, r.okuma), 26)}`); } console.log(`\nkopya sayisi arttikca cogaltma akisi birincilden daha cok cekilir: gecikme ` + `${gecikmeR(1).toFixed(2)} sn (1 kopya) -> ${gecikmeR(8).toFixed(2)} sn (8 kopya).`); console.log("kopya | gecikme | kopya basina okuma/sn | eklenen kopyanin kazanci | bayat pay | birincil yuk (birim/sn)"); console.log("------|---------|-----------------------|--------------------------|-----------|------------------------"); const W = 1, yon = yonlenen(r, W) / PENCERE, kopyaOkuma = (r.okuma / PENCERE) - yon; let onceki = null; for (const R of [1, 2, 3, 4, 5, 6, 7, 8]) { const basina = kopyaOkuma / R; const marj = onceki === null ? "-" : (onceki - basina).toFixed(1) + "/sn"; const b = bayat(r, gecikmeR(R)); const yuk = (r.yazma / PENCERE) * YUK_YAZMA + yon * YUK_OKUMA + R * (r.yazma / PENCERE) * YUK_COGALTMA; console.log(`${s(R, 5)} | ${s(gecikmeR(R).toFixed(2) + " sn", 7)} | ${s(basina.toFixed(1), 21)} | ` + `${s(marj, 24)} | ${s(y(b, r.okuma), 9)} | ${s(yuk.toFixed(1), 23)}`); onceki = basina; } console.log(`\nkosumdan bagimsiz: yapiskan pencere kopya gecikmesinden buyuk oldugunda kendi ` + `yazdigini goremeyen istek kalmaz; bedeli birincile giden okuma sayisidir.`); // Aktarim bedeli: bolge disindaki her kopya her yazmayi bolge sinirindan gecirir. Kurgu birim. const KAYIT_KB = 1.8, AY = 2592000, BOYUT_GB = 220; const gbAy = (r.yazma / PENCERE) * KAYIT_KB * AY / 1048576; console.log(`\ncogaltma akisi: ${(r.yazma / PENCERE).toFixed(0)} yazma/sn x ${KAYIT_KB} KB = ` + `${gbAy.toFixed(0)} GB/ay, kopya basina.`); console.log("kopya yerlesimi | birim/GB | 1 kopya | 2 kopya | 3 kopya (kurgu birim/ay)"); console.log("----------------|----------|---------|---------|---------"); for (const [ad, birim] of [["ayni bolge", 0], ["baska bolge", 2]]) console.log(`${ad.padEnd(15)} | ${s(birim, 8)} | ${s((birim * gbAy).toFixed(0), 7)} | ` + `${s((2 * birim * gbAy).toFixed(0), 7)} | ${s((3 * birim * gbAy).toFixed(0), 7)}`); console.log(`geri alinamayan kalem: yukseltilen kopya eski cogaltma bagina donmez; bagi yeniden ` + `kurmak ${BOYUT_GB} GB tam kopya demektir.`); console.log(`bolge ici 95 MB/sn ile ${(BOYUT_GB * 1024 / 95 / 3600).toFixed(2)} sa; bolgeler arasi ` + `30 MB/sn ile ${(BOYUT_GB * 1024 / 30 / 3600).toFixed(2)} sa + ${2 * BOYUT_GB} kurgu birim.`);
420000 istek / 300 sn: 92400 yazma, 327600 okuma. 2400 oturum, 50000 is emri. Tohum 20260802.
yazmalarin %31 kadari ayni oturum tarafindan geri okunur.
kopya gecikmesi | bayat okuma | bayat pay | kendi yazdigini goremeyen | KYO pay
----------------|-------------|-----------|---------------------------|---------
0.10 sn | 208 | %0.06 | 0 | %0.00
0.25 sn | 5253 | %1.60 | 4755 | %1.45
0.50 sn | 14702 | %4.49 | 13733 | %4.19
1.00 sn | 30039 | %9.17 | 28093 | %8.58
2.00 sn | 31877 | %9.73 | 28093 | %8.58
5.00 sn | 37473 | %11.44 | 28093 | %8.58
yonlendirme kurali, kopya gecikmesi 0.55 sn sabit (15546 istek kendi yazdigini goremiyor):
yapiskan pencere W | birincile giden okuma | kurtarilan | kalan | birincile kayan okuma payi
-------------------|-----------------------|------------|-------|---------------------------
0.00 sn | 0 | 0 | 15546 | %0.00
0.25 sn | 14986 | 5078 | 10468 | %4.57
0.50 sn | 33134 | 13843 | 1703 | %10.11
1.00 sn | 64155 | 15546 | 0 | %19.58
2.00 sn | 95648 | 15546 | 0 | %29.20
5.00 sn | 168901 | 15546 | 0 | %51.56
15.00 sn | 278984 | 15546 | 0 | %85.16
kopya sayisi arttikca cogaltma akisi birincilden daha cok cekilir: gecikme 0.40 sn (1 kopya) -> 1.45 sn (8 kopya).
kopya | gecikme | kopya basina okuma/sn | eklenen kopyanin kazanci | bayat pay | birincil yuk (birim/sn)
------|---------|-----------------------|--------------------------|-----------|------------------------
1 | 0.40 sn | 878.1 | - | %3.34 | 418.2
2 | 0.55 sn | 439.1 | 439.1/sn | %5.08 | 442.8
3 | 0.70 sn | 292.7 | 146.4/sn | %6.79 | 467.5
4 | 0.85 sn | 219.5 | 73.2/sn | %8.53 | 492.1
5 | 1.00 sn | 175.6 | 43.9/sn | %9.17 | 516.7
6 | 1.15 sn | 146.4 | 29.3/sn | %9.27 | 541.4
7 | 1.30 sn | 125.5 | 20.9/sn | %9.35 | 566.0
8 | 1.45 sn | 109.8 | 15.7/sn | %9.44 | 590.7
kosumdan bagimsiz: yapiskan pencere kopya gecikmesinden buyuk oldugunda kendi yazdigini goremeyen istek kalmaz; bedeli birincile giden okuma sayisidir.
cogaltma akisi: 308 yazma/sn x 1.8 KB = 1370 GB/ay, kopya basina.
kopya yerlesimi | birim/GB | 1 kopya | 2 kopya | 3 kopya (kurgu birim/ay)
----------------|----------|---------|---------|---------
ayni bolge | 0 | 0 | 0 | 0
baska bolge | 2 | 2741 | 5482 | 8223
geri alinamayan kalem: yukseltilen kopya eski cogaltma bagina donmez; bagi yeniden kurmak 220 GB tam kopya demektir.
bolge ici 95 MB/sn ile 0.66 sa; bolgeler arasi 30 MB/sn ile 2.09 sa + 440 kurgu birim.
Gecikme Bir Sayı, Yansıması Bir Eğridir
İlk tablo gecikmenin isteğe nasıl çevrildiğini gösteriyor. 0,1 saniyede 327.600 okumanın yalnızca 208’i bayat; yarım saniyede 14.702, bir saniyede 30.039. Eğri doğrusal değil, çünkü bayat okuma sayısı gecikmeyle değil, gecikme penceresine düşen yazma yoğunluğuyla artar.
Sağ sütun asıl bilgiyi taşıyor. 0,25 saniyelik gecikmedeki 5.253 bayat okumanın 4.755’i, yani yüzde 90’ı, kendi yazdığını göremeyen isteklerdir. Sebep YV9’dur: geri okumalar yazmadan hemen sonra gelir, dar bir gecikme penceresine düşen okumaların neredeyse tamamı geri okumadır.
Gecikme 1 saniyeden 5 saniyeye çıkınca toplam bayat okuma 30.039’dan 37.473’e yükseliyor ama kendi yazdığını göremeyen istek 28.093’te sabit kalıyor: geri okumalar en geç 900 ms sonra geldiği için 1 saniyeyi aşan gecikmede zaten hepsi bayattır. Gecikmeyi büyütmek yeni bir hata türü üretmiyor, mevcut hatanın etrafına daha çok tutarsızlık ekliyor.
Yönlendirme Kuralı Kurtarır, Faturayı Birincile Keser
İkinci tablo gecikmeyi 0,55 saniyede sabitleyip yapışkan pencereyi tarıyor. Kural uygulamanın bildiği tek şeye dayanıyor: bir oturum yazdıktan sonra W saniye boyunca okumaları kopyaya değil birincile gider.
W sıfırken kural yoktur ve 15.546 istek kendi yazdığını göremez. W 0,25 saniyeye çıktığında 5.078’i kurtarılıyor, 10.468’i kalıyor — pencere gecikmeden dar olduğu için yetmiyor. W 0,5’te kalan 1.703’e iniyor. W 1 saniyede kalan sıfırdır ve bu satır koşumdan bağımsızdır: yapışkan pencere kopya gecikmesini aştığı anda, kendi yazmasından etkilenen her okuma birincile gider.
Bedel sağ sütunda. Kalanı sıfırlayan W = 1 ayarı, okumaların yüzde 19,58’ini birincile kaydırıyor: 327.600 okumanın 64.155’i. Kopyaları açmanın amacı birincili boşaltmaktı; kural o kazancın beşte birini geri veriyor. W’yi güvenli olsun diye 15 saniyeye çekmek yüzde 85,16’ya çıkarıyor ve kopyalar boşa düşer. Doğru ayar en büyük W değil, gecikmenin biraz üzerindeki W’dir; gecikme kopya sayısına bağlı olduğu için iki karar birbirine bağlıdır.
Kopya Eklemenin Azalan Getirisi
Üçüncü tablo kopya sayısını 1’den 8’e çıkarıyor. Kopya başına düşen okuma 878,1’den 109,8’e iniyor; beklenen budur. Kazanç sütunu beklenmeyeni gösteriyor: ikinci kopya 439,1 okuma/sn hafifletiyor, üçüncüsü 146,4, dördüncüsü 73,2, sekizincisi 15,7. Yedinci ve sekizinci kopya birlikte, ikinci kopyanın kazancının yüzde 8’ini getiriyor.
İki sütun daha bu tabloyu tersine çeviriyor. Gecikme kopya sayısıyla büyüyor (YV10): 8 kopyada 1,45 saniye ve bayat okuma payı yüzde 3,34’ten yüzde 9,44’e çıkıyor. Birincil yük de büyüyor: 418,2 birimden 590,7 birime, çünkü her kopyaya çoğaltma akışı gönderilir. Sekizinci kopya eklendiğinde birincil yüzde 41 daha yüklüdür ve okuma tarafında kazandığı 15,7 istek/sn’dir. Bu noktadan sonra kopya eklemek yükü dağıtmaz, taşır.
Aktarım Bedeli ve Geri Alınamayan Kalem
Son blok kopyanın yerleşimini ücretlendiriyor. Çoğaltma akışı saniyede 308 yazma × 1,8 KB, yani kopya başına ayda 1.370 GB: aynı bölgede 0 kurgu birim, başka bölgede 2.741, üç kopya için 8.223. Kopyaların bölgeye dağıtılması dayanıklılık kararı gibi görünür; faturada bir aktarım kalemidir ve yazma hızıyla ölçeklenir, veri boyutuyla değil.
Geri alınamayan kalem bu derste incedir. Bir kopya birincile yükseltildiğinde eski çoğaltma bağına dönmez; bağı yeniden kurmak 220 GB’lik tam bir kopya demektir: bölge içinde 0,66 saat, bölgeler arasında 2,09 saat ve 440 kurgu birim. Yükseltme düğmesine basmak bir saniyelik iştir, geri dönüşü değildir.
Özet
- Kopya gecikmesi 0,1 saniyeden 5 saniyeye çıkınca bayat okuma 208’den 37.473’e yükseliyor; eğri doğrusal değil, gecikme penceresine düşen yazma yoğunluğuna bağlıdır.
- Dar gecikmede bayat okumaların yüzde 90’ı kendi yazdığını göremeyen isteklerdir; gecikme 1 saniyeyi aştıktan sonra bu sayı 28.093’te sabitlenir, yalnızca çevresindeki tutarsızlık artar.
- Yapışkan pencere gecikmeyi aştığında (W = 1 sn, gecikme 0,55 sn) kendi yazdığını göremeyen istek sıfırlanır; bedeli okumaların yüzde 19,58’inin birincile kaymasıdır.
- Pencereyi 15 saniyeye açmak aynı 15.546 isteği kurtarır ama okumaların yüzde 85,16’sını birincile taşır: kopyaları açmanın kazancı büyük ölçüde geri verilir.
- Kopya eklemenin getirisi azalıyor (439,1 → 15,7 okuma/sn) ve iki maliyet artıyor: gecikme 0,40’tan 1,45 saniyeye, birincil yük 418,2’den 590,7 birime.
- Bölge dışı kopya yazma hızıyla ölçeklenen bir aktarım kalemidir (ayda 1.370 GB, 2.741 kurgu birim); yükseltilen kopya çoğaltma bağına dönmez, yeniden kurmak 220 GB’lik tam kopyadır.
Sonraki Adım
Bu iki ders ilişkisel veritabanının kiralanmasını ölçtü ve elde kalan kararların çoğu ayardı: yanlış seçilen bir yapışkan pencere değiştirilebilir, fazla kopya kapatılabilir. Sonraki ders aynı soruyu anahtar–değer tarafında soruyor ve orada tabloyu tersine çeviren tek bir kalem var: veri seçilen bölüm anahtarına göre yerleşir ve anahtar seçildikten sonra hangi sorguların karşılanabileceği sabitlenir. Üç aday anahtar aynı gerçek anahtar dağılımında koşturulacak, en yoğun bölümün payı ve anahtarla desteklenmeyen erişim örüntüsü sayılacak, sonra anahtarı değiştirmenin bedeli bayt ve süre olarak hesaplanacak.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.