Ders 06 / 14
Arşiv Depolama
Arşiv katmanında saklama ücretinin düşmesine karşılık geri getirmenin hem ücretli hem gecikmeli olması: üç geri getirme hızının süre ve ücretle birlikte taranması, bir denetim isteğinde kaç saat beklendiğinin çıkarılması, çıkış ücretinin getirmenin üstüne binmesi ve en az saklama süresinin erken silinen nesneye tam süreyi ödetmesi.
İçindekiler
İkinci derste erişim geçmişi taranınca bir aile ayrıldı: saha fotoğraflarının yüzde 97’si yıl boyunca hiç açılmadı. Böyle veri için sık erişilen sınıf açık bir israftır ve üçüncü dersin yaşam döngüsü kuralı onu otomatik olarak arşive gönderebilir. Arşive gönderilen verinin ne olduğu ise henüz ölçülmedi.
Arşiv katmanı bir depolama sınıfıdır ama diğerlerinden bir noktada ayrılır: veri hemen okunamaz. Bir nesneyi almak için önce bir geri getirme isteği verilir, istek işlenir, nesne okunabilir hâle gelir. Bu bekleme dakikalardan saatlere uzanır ve hızlandırılabilir — ücreti ödendiği sürece. Bu dersin ölçüsü budur: saklamada kazanılanın nerede, hangi kalemle geri ödendiği.
- DT31 — Arşiv katmanı, geri getirme hızları ve ücretler kurgudur; katmanlar erişim sıklığıyla anılır.
- DT32 — Üç geri getirme hızı vardır; her birinin ilk yanıt gecikmesi, akış hızı, bayt ücreti ve istek ücreti modelde yazılıdır.
- DT33 — Bir geri getirme isteği en çok 10.000 nesne alır ve aynı anda dört parti işlenir.
// arsiv/model.mjs — arsiv katmani, geri getirme hizlari ve denetim istegi MODELDIR. Ucretler kurgu // birimdir; katmanlar erisim sikligiyla anilir, hicbir ticari ad kullanilmaz. export const SINIF = { // saklama B/GiB/ay, gecis B/istek, enAzGun: en az saklama "sik erisilen": { saklama: 0.0230, gecis: 0.0050 / 1000, enAzGun: 0 }, arsiv: { saklama: 0.0010, gecis: 0.0500 / 1000, enAzGun: 180 }, }; // Geri getirme hizlari: ilk yanit gecikmesi, akis hizi, bayt ve istek ucreti. export const HIZ = { yavas: { ilkSaat: 12, gibSaat: 250, gib: 0.0025, istek: 0.030 / 1000 }, orta: { ilkSaat: 4, gibSaat: 600, gib: 0.0100, istek: 0.060 / 1000 }, hizli: { ilkSaat: 5 / 60, gibSaat: 1500, gib: 0.0300, istek: 0.120 / 1000 }, }; export const PARTI = 10_000, ES_ZAMANLI = 4; // bir istekte 10.000 nesne, ayni anda 4 parti export const CIKIS = { "bolge ici": 0, "bolgeler arasi": 0.020, internete: 0.085 }; // Kurgu denetim istegi: bir ilin uc yillik fatura belgeleri ve saha fotograflari. export const DENETIM = { fatura: { adet: 46_000, kib: 380 }, foto: { adet: 80_000, kib: 3686 } }; export const GIB = (bayt) => bayt / 1024 ** 3; export const denetimBayt = Object.values(DENETIM).reduce((a, k) => a + k.adet * k.kib * 1024, 0); export const denetimAdet = Object.values(DENETIM).reduce((a, k) => a + k.adet, 0);
Süre ile Ücret Aynı Kadranın İki Ucu
- DT34 — Kurgu denetim isteği bir ilin üç yıllık fatura belgelerini ve saha fotoğraflarını kapsar; adetler ve boyutlar modelde yazılıdır.
// arsiv/getirme.mjs — geri getirme hizlari taranir: sure ile ucret birlikte sayilir import { HIZ, PARTI, ES_ZAMANLI, CIKIS, GIB, denetimBayt, denetimAdet, DENETIM } from "./model.mjs"; const g = (x, n, d = 2) => x.toFixed(d).padStart(n); const s = (x, n) => String(x).padStart(n); const gib = GIB(denetimBayt), parti = Math.ceil(denetimAdet / PARTI), tur = Math.ceil(parti / ES_ZAMANLI); console.log(`kurgu denetim istegi: ${Object.entries(DENETIM).map(([a, k]) => `${k.adet} ${a}`).join(" + ")} = ` + `${denetimAdet.toLocaleString("tr")} nesne, ${g(gib, 0, 1)} GiB.`); console.log(`istek ${PARTI} nesnelik partilere boluniyor: ${parti} parti, ayni anda ${ES_ZAMANLI} parti, ${tur} tur.`); console.log("\nhiz | ilk yanit | akis GiB/saat | tek parti (saat) | toplam bekleme (saat) | getirme ucreti"); console.log("-------|-----------|---------------|------------------|-----------------------|---------------"); const U = {}, T = {}; for (const [ad, h] of Object.entries(HIZ)) { const partiGib = gib / parti, turSaat = h.ilkSaat + (partiGib * ES_ZAMANLI) / h.gibSaat; const ucret = U[ad] = gib * h.gib + denetimAdet * h.istek; T[ad] = tur * turSaat; console.log(`${ad.padEnd(6)} | ${g(h.ilkSaat, 9, 2)} | ${s(h.gibSaat, 13)} | ${g(h.ilkSaat + partiGib / h.gibSaat, 16, 2)} | ` + `${g(T[ad], 21, 1)} | ${g(ucret, 14, 2)}`); } console.log(`ayni istek: bekleme ${(T.yavas / T.hizli).toFixed(0)} kat kisaliyor, ucret ` + `${(U.hizli / U.yavas).toFixed(1)} kat artiyor. Sure ile ucret ayni kadranin iki ucu.`); console.log(`istek ucreti baskin: ${denetimAdet.toLocaleString("tr")} nesne yavas hizda ` + `${g(denetimAdet * HIZ.yavas.istek, 0, 2)} birim, ayni bayt icin bayt ucreti ${g(gib * HIZ.yavas.gib, 0, 2)} birim.`); console.log("\ngetirme bittikten sonra cikis ayrica odenir (ayni bayt):"); for (const [nere, oran] of Object.entries(CIKIS)) console.log(` ${nere.padEnd(15)} ${g(gib * oran, 7)} birim`); console.log(`internete indirilirse cikis ucreti, en ucuz getirmenin ${g(gib * CIKIS.internete / U.yavas, 0, 1)} kati: ` + `arsivin ucuzlugu veriyi disari cikarmaya kadardir.`); // Karar: verilen yanit suresi taahhudune uyan en ucuz hiz hangisi. Istek daraltilirsa ne degisir. const cozum = (adet, bayt, sinirSaat) => { const G = GIB(bayt), p = Math.ceil(adet / PARTI), t = Math.ceil(p / ES_ZAMANLI); let en = null; for (const [ad, h] of Object.entries(HIZ)) { const sure = t * (h.ilkSaat + (G / p * ES_ZAMANLI) / h.gibSaat), uc = G * h.gib + adet * h.istek; if (sure <= sinirSaat && (en === null || uc < en.uc)) en = { ad, sure, uc }; } return en; }; console.log("\nyanit suresi taahhudune uyan en ucuz hiz:"); console.log("taahhut | tam istek (126.000 nesne) | yalniz fatura (46.000 nesne)"); console.log("--------|----------------------------------|------------------------------"); for (const sinir of [1, 6, 24, 72]) { const a = cozum(denetimAdet, denetimBayt, sinir); const f = cozum(DENETIM.fatura.adet, DENETIM.fatura.adet * DENETIM.fatura.kib * 1024, sinir); const yaz = (x) => x ? `${x.ad.padEnd(5)} ${g(x.sure, 5, 1)} saat ${g(x.uc, 7)} birim` : "karsilanamaz"; console.log(`${s(sinir + " saat", 7)} | ${yaz(a).padEnd(32)} | ${yaz(f)}`); }
kurgu denetim istegi: 46000 fatura + 80000 foto = 126.000 nesne, 297.9 GiB. istek 10000 nesnelik partilere boluniyor: 13 parti, ayni anda 4 parti, 4 tur. hiz | ilk yanit | akis GiB/saat | tek parti (saat) | toplam bekleme (saat) | getirme ucreti -------|-----------|---------------|------------------|-----------------------|--------------- yavas | 12.00 | 250 | 12.09 | 49.5 | 4.52 orta | 4.00 | 600 | 4.04 | 16.6 | 10.54 hizli | 0.08 | 1500 | 0.10 | 0.6 | 24.06 ayni istek: bekleme 86 kat kisaliyor, ucret 5.3 kat artiyor. Sure ile ucret ayni kadranin iki ucu. istek ucreti baskin: 126.000 nesne yavas hizda 3.78 birim, ayni bayt icin bayt ucreti 0.74 birim. getirme bittikten sonra cikis ayrica odenir (ayni bayt): bolge ici 0.00 birim bolgeler arasi 5.96 birim internete 25.32 birim internete indirilirse cikis ucreti, en ucuz getirmenin 5.6 kati: arsivin ucuzlugu veriyi disari cikarmaya kadardir. yanit suresi taahhudune uyan en ucuz hiz: taahhut | tam istek (126.000 nesne) | yalniz fatura (46.000 nesne) --------|----------------------------------|------------------------------ 1 saat | hizli 0.6 saat 24.06 birim | hizli 0.2 saat 6.02 birim 6 saat | hizli 0.6 saat 24.06 birim | hizli 0.2 saat 6.02 birim 24 saat | orta 16.6 saat 10.54 birim | orta 8.0 saat 2.93 birim 72 saat | yavas 49.5 saat 4.52 birim | yavas 24.1 saat 1.42 birim
Denetim isteği 126.000 nesne ve 297,9 GiB’dir. Üç hızın hiçbiri yanlış değildir; farkları iki sütunda toplanır. Yavaş hızda toplam bekleme 49,5 saattir — iki günden fazla — ve getirme ücreti 4,52 birimdir. Hızlı hızda bekleme 0,6 saate iner, ücret 24,06 birime çıkar. Bekleme 86 kat kısalır, ücret 5,3 kat artar. Bir denetim isteğinde asıl karar hangi hızın “iyi” olduğu değil, kaç saat beklemenin kabul edilebilir olduğudur; o cevap bilinmeden hız seçilemez.
Toplam beklemenin ilk yanıt gecikmesinden büyük olmasının nedeni parti hesabıdır. İstek 10.000 nesnelik partilere bölünür: 126.000 nesne 13 parti eder, aynı anda dört parti işlenir, dolayısıyla dört tur gerekir. Yavaş hızda tek parti 12,09 saat sürer ama toplam 49,5 saattir. İlk yanıt gecikmesi her turda yeniden ödenir ve nesne sayısı arttıkça bekleme baytla değil turla büyür.
Alt satır aynı yapının fiyat tarafını gösteriyor: 126.000 nesnenin istek ücreti yavaş hızda 3,78 birimdir, aynı baytın bayt ücreti ise 0,74 birim. Getirme faturasının beşte dördü nesne sayısındandır. Bu, birinci ve ikinci dersteki kuralın arşivdeki karşılığıdır — küçük ve çok sayıda nesne her katmanda istek ücretiyle ödetir.
Çıkış ayrı bir kalemdir. Geri getirme, veriyi okunabilir hâle getirir; veriyi bir yere taşımaz. Aynı 297,9 GiB bölge içinde kalırsa çıkış ücreti doğmaz, bölgeler arasına taşınırsa 5,96 birim, internete indirilirse 25,32 birim tutar. İnternete indirme, en ucuz getirmenin 5,6 katıdır: arşivin ucuzluğu veriyi dışarı çıkarmaya kadardır.
Son tablo kararı yanıt süresi taahhüdüne bağlıyor ve seçimi tek satıra indiriyor. Bir saatlik taahhütte yalnız hızlı hız yeter ve 24,06 birim tutar; yirmi dört saatlik taahhütte orta hız 10,54 birime düşer; yetmiş iki saatlik taahhütte yavaş hız 4,52 birimle yeter. Sağ sütun ikinci bir kolu açıyor: denetim isteği daraltılıp yalnız fatura belgeleri istendiğinde her taahhütte hem süre hem ücret düşer — yirmi dört saatlik taahhütte 10,54 birim yerine 2,93 birim. İsteği daraltmak, hızı yükseltmekten ucuzdur; arşivde ölçülmesi gereken ilk şey neyin gerçekten geri getirilmesi gerektiğidir.
En Az Saklama Süresi
- DT35 — Arşiv katmanının en az saklama süresi 180 gündür ve nesne sınıfa girdiği anda başlar.
- DT36 — Yaşam döngüsü kuralı nesneyi 30. günde arşive geçirir, ömrü bitince siler.
// arsiv/enaz.mjs — en az saklama suresi: erken silinen nesne yine de tam sure ucretlendirilir import { SINIF, GIB } from "./model.mjs"; const AY_GUN = 30, arsiv = SINIF.arsiv, sik = SINIF["sik erisilen"]; const enAzAy = arsiv.enAzGun / AY_GUN; // Iki aile, iki omur: kucuk ve kisa omurlu belge, buyuk ve uzun omurlu fotograf. const AILE = [ { ad: "fatura-belgeleri", adet: 86_000, kib: 380, omurAy: 3 }, { ad: "saha-fotograflari", adet: 42_000, kib: 3686, omurAy: 60 }, ]; const GECIS_AY = 1; // 30. gunde arsive gecen kural const g = (x, n, d = 2) => x.toFixed(d).padStart(n); const s = (x, n) => String(x).padStart(n); console.log(`arsiv katmaninin en az saklama suresi ${arsiv.enAzGun} gun = ${enAzAy} ay. ` + `Kural ${GECIS_AY}. ayda arsive geciriyor, omur bitince siliyor.`); console.log("\naile | omur | arsivde gecen | faturalanan | gecis ucreti | arsivsiz | arsivli | oran"); console.log("------------------|-------|---------------|-------------|--------------|----------|---------|------"); for (const f of AILE) { const gib = GIB(f.adet * f.kib * 1024), arsivde = f.omurAy - GECIS_AY; const faturalanan = Math.max(arsivde, enAzAy); const gecisUcret = f.adet * arsiv.gecis; const arsivsiz = gib * sik.saklama * f.omurAy; const arsivli = gib * sik.saklama * GECIS_AY + gecisUcret + gib * arsiv.saklama * faturalanan; console.log(`${f.ad.padEnd(17)} | ${s(f.omurAy + " ay", 5)} | ${s(arsivde + " ay", 13)} | ${s(faturalanan + " ay", 11)} | ` + `${g(gecisUcret, 12)} | ${g(arsivsiz, 8)} | ${g(arsivli, 7)} | ${g(arsivli / arsivsiz, 5, 2)}`); } // Erken silme: nesne 45. gunde silinse de 180 gunluk borc duruyor. const foto = AILE[1], gib = GIB(foto.adet * foto.kib * 1024), SILME_GUN = 45; const kullanilan = SILME_GUN / AY_GUN, borclu = enAzAy - kullanilan; console.log(`\nerken silme: ${foto.adet.toLocaleString("tr")} fotograf arsive konup ${SILME_GUN}. gunde silindi.`); console.log(` kullanilan ${g(kullanilan, 0, 1)} ay, faturalanan ${enAzAy} ay, odenen bos sure ${g(borclu, 0, 1)} ay.`); console.log(` ${SILME_GUN}. gunde silmenin faturasi ${g(gib * arsiv.saklama * enAzAy, 0, 3)} birim; ` + `hic silmeyip ${enAzAy} ay tutmanin faturasi da ${g(gib * arsiv.saklama * enAzAy, 0, 3)} birim.`); console.log(` aradaki ${g(borclu, 0, 1)} ay icin ${g(gib * arsiv.saklama * borclu, 0, 3)} birim, artik var olmayan ` + `nesneler icin odeniyor: erken silmek hicbir sey kazandirmiyor.`); console.log(`arsiv, ${enAzAy} aydan kisa yasayacak veri icin bir depolama sinifi degil, pesin odenmis bir borctur.`);
arsiv katmaninin en az saklama suresi 180 gun = 6 ay. Kural 1. ayda arsive geciriyor, omur bitince siliyor. aile | omur | arsivde gecen | faturalanan | gecis ucreti | arsivsiz | arsivli | oran ------------------|-------|---------------|-------------|--------------|----------|---------|------ fatura-belgeleri | 3 ay | 2 ay | 6 ay | 4.30 | 2.15 | 5.20 | 2.42 saha-fotograflari | 60 ay | 59 ay | 59 ay | 2.10 | 203.74 | 14.21 | 0.07 erken silme: 42.000 fotograf arsive konup 45. gunde silindi. kullanilan 1.5 ay, faturalanan 6 ay, odenen bos sure 4.5 ay. 45. gunde silmenin faturasi 0.886 birim; hic silmeyip 6 ay tutmanin faturasi da 0.886 birim. aradaki 4.5 ay icin 0.664 birim, artik var olmayan nesneler icin odeniyor: erken silmek hicbir sey kazandirmiyor. arsiv, 6 aydan kisa yasayacak veri icin bir depolama sinifi degil, pesin odenmis bir borctur.
Tablo tek bir kuralı iki aileye uyguluyor ve zıt sonuç veriyor. Saha fotoğrafları altmış ay yaşar; arşivde geçen elli dokuz ay en az saklama süresinin çok üstündedir, dolayısıyla faturalanan süre de elli dokuz aydır. Arşivsiz 203,74 birim tutan aile arşivle 14,21 birime iner — oran 0,07, on dört kat kazanç. Fatura belgeleri üç ay yaşar; arşivde iki ay geçirir ama altı ay faturalanır. Arşivsiz 2,15 birim tutan aile arşivle 5,20 birime çıkar: 2,42 kat zarar. Aynı kural, aynı katman, ters sonuç. Farkı yaratan iki şey vardır — nesnenin ömrü ve nesnenin boyutu. 86.000 küçük belgenin geçiş ücreti tek başına 4,30 birimdir, arşivsiz toplamın iki katı.
Erken silme bloğu kalemi adıyla yazıyor. Kırk iki bin fotoğraf arşive konup kırk beşinci günde siliniyor: kullanılan 1,5 ay, faturalanan 6 ay. Silmenin faturası 0,886 birimdir ve hiç silmeyip altı ay tutmanın faturası da 0,886 birimdir — birebir aynı. Aradaki 4,5 ay için ödenen 0,664 birim, artık var olmayan nesneler içindir. En az saklama süresi bu dersin geri alınamayan kalemidir: nesne sınıfa girdiği anda borç doğar, ve o borcu silme de, sınıf değiştirme de kapatmaz.
Devredilen karar tarafı burada en geniştir. Arşiv katmanında dayanıklılık, yerleşim, saklama ortamı, onarım ve okunabilirliğin sürdürülmesi tümüyle sağlayıcıdadır; hiçbiri görünmez, hiçbirinin kadranı yoktur. Elde kalan üç sayı vardır: hangi nesnenin ne zaman arşive gireceği, ne kadar yaşayacağı ve gerektiğinde hangi hızla geri getirileceği. Üçü de veriyi yazmadan önce kararlaştırılır, çünkü üçünün de bedeli sonradan ödenir.
Özet
- Arşiv katmanında saklama ucuzdur ama veri hemen okunamaz: aynı denetim isteği yavaş hızda 49,5 saat bekletip 4,52 birim, hızlı hızda 0,6 saat bekletip 24,06 birim tutar.
- Bekleme baytla değil turla büyür: 126.000 nesne 10.000’lik partilere bölünür, dört tur eder ve ilk yanıt gecikmesi her turda yeniden ödenir.
- Getirme faturasının beşte dördü nesne sayısındandır: 126.000 nesnenin istek ücreti 3,78, aynı baytın bayt ücreti 0,74 birimdir.
- Geri getirme veriyi okunabilir yapar, taşımaz: aynı 297,9 GiB internete indirilirse 25,32 birim çıkış ücreti getirmenin üstüne biner, en ucuz getirmenin 5,6 katı.
- En az saklama süresi geri alınamayan kalemdir: altmış ay yaşayan fotoğraflarda arşiv on dört kat kazandırır, üç ay yaşayan belgelerde 2,42 kat zarar ettirir; kırk beşinci günde silinen nesne yine de altı ay öder.
Sonraki Adım
Altı ders verinin nereye konacağını ölçtü: nesne, blok, paylaşımlı dosya ve arşiv. Hiçbiri tek bir soruyu sormadı — bu veriyi kim okuyabilir. Kurgu ölçüm ağında saha ekipleri fotoğrafları telefondan açar, denetçiler fatura belgelerini dışarıdan ister ve iki grubun da kova erişimi yoktur. Kimlik vermek kalıcı bir kapı açar; oysa istenen şey genellikle süreli ve dar bir kapıdır. Sonraki ders bunu ölçer: imzalı bağlantı üretilir, süresi ve kapsamı gerçekten doğrulanır. Ölçülecek üç şey var — bağlantının ömrü kısaldıkça artan yeniden üretme yükü, uzadıkça büyüyen sızıntı penceresi, ve kapsam genişledikçe tek bir bağlantının açtığı nesne sayısı.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.