Ders 08 / 10
Yinelemeye Dayanıklılık ve Yeniden İşleme
Aynı yükün ikinci kez işlenmesinin satırı çoğalttığının ve sunulan sayının bunu göstermediğinin ölçülmesi: ekleyen depoda bir dönemin geri doldurulması ham satırı 2400'den 2600'e, tam yeniden koşum 4800'e çıkarıyor, üç koşumda 7200'e ulaşıyor, ama tekilleştirme aşaması fazlalığı yuttuğu için sunulan değer üç koşumda da 1212,55 kalıyor; aynı aşama yeniden verilen yük bir düzeltme taşıdığında düzeltmeyi çöpe atıp değeri 794,36'da bırakıyor; tekilleştirme anahtar yerine satırın tamamına baktığında ise aynı yeniden koşumlar değeri 2425,09'a ve 3637,64'e taşıyor.
İçindekiler
Önceki ders sözleşmenin bozulmayı aşama 0’da yakaladığını gösterdi, ama yakalamak düzeltmek değildir: engellenen 200 satır bir yerde bekler, üretici düzeltir ve o dönem hatta yeniden verilir. Buraya kadarki hiçbir ölçümde hat aynı veriyi iki kez görmedi.
İkinci koşum bir istisna değil, hattın en sık yaptığı iştir. Üretici bir yükü düzeltir, bir aşama hata verip yeniden denenir, geçmiş bir dönem geri doldurulur. Bu ders aynı yükü iki kez işleyen bir hattın satır sayısına ne olduğunu, hangi aşamanın fazlalığı yuttuğunu ve sunulan değerin bunu gösterip göstermediğini sayar. Yanıt kursun üçüncü iddiasının en temiz örneğidir.
- VK14. Kaynak, hat ve depo kurgudur; gerçek bir depo, dosya biçimi ya da orkestratör çağrılmaz. Tohum 20260218, ölçü koşumdan bağımsızdır.
- VK15.
idempotentkarşılığı bu müfredatta yinelemeye dayanıklıdır. Kavramın kendisi Kabuk Programlama kursunda, yeniden deneme ile kuyruk yordamı Önbellekleme, Kuyruklar ve Eşzamansız İşleme kursunda ölçüldü ve tekrarlanmaz. Buradaki soru yalnızca yeniden işlemenin satırı çoğaltıp çoğaltmadığıdır. - VK16. Yeniden işleme bir kaza değildir: düzeltilmiş yük, yeniden denenen aşama ve geri doldurulan dönem sıradan işlerdir.
- VK17. Yeniden verilen satırın değeri aynı kalır, yalnızca yükleme damgası değişir; tek istisna düzeltme taşıyan yüktür. Bu ayrıntı son iki ölçümün tamamını belirler.
- VK18. Taban çizgisi tek koşumdur: ham satır 2400, çoğalan satır 0.
- VK19. Sayılan birimler: yeniden işlenen satır, çoğalan satır, tekilleştirmenin düşürdüğü satır ve sunumdaki fark. Ham süre yazılmaz, ölçü koşum olarak yazılır.
- VK20. Çözünürlük: satır oranının adımı 0,0004, özet hücresinin 0,0182, sunum değerinin 0,2000. Sunum üzerinde oran basılmaz.
İki Yazma Biçimi
Bir hattın yinelemeye dayanıklı olup olmadığı tek bir kararla belirlenir: gelen satır depoya nasıl yazılıyor. Ekleyen yazma satırı deponun sonuna koyar; aynı satır iki kez geldiğinde depoda iki kez durur. Anahtarlayan yazma satırı bir anahtarın üzerine yazar; aynı anahtar iki kez geldiğinde depoda bir kez durur. Anahtar burada abone ile dönemin çiftidir, yani hattın zaten tekillik ölçütü olarak kullandığı şey.
İkinci parça yeniden işlemenin nasıl göründüğüdür. Düzeltilmiş yük geldiğinde satırın değeri aynıdır; değişen tek şey yükleme damgasıdır. Bu, kolay gözden kaçan bir ayrıntıdır ve son ölçümün tamamı buna dayanır.
# KURGUDUR. Sayac okumalari, bes asamali hat ve depo ders icinde tanimlanir; # gercek bir depo, dosya bicimi ya da orkestrator cagrilmaz. TOHUM, M32 = 20260218, 0xFFFFFFFF def uretec(t): x = ((t ^ (t >> 16)) * 2246822507) & M32 x = ((x ^ (x >> 13)) * 3266489909) & M32 s = [(x ^ (x >> 16)) & M32] def sonraki(): s[0] = (s[0] * 1664525 + 1013904223) & M32 return s[0] / 4294967296 return sonraki BOLGE = ["dogu", "bati", "kuzey", "guney", "merkez"] TIP = ["mesken", "isyeri"] DONEM = [f"2026-{a:02d}" for a in range(1, 13)] ABONE = {} for i in range(200): r = uretec(TOHUM + 37 * i) ABONE[f"A{i + 1:03d}"] = {"bolge": BOLGE[int(r() * 5)], "tip": TIP[int(r() * 2)], "baslangic": 10000 + int(r() * 60000)} def kaynak_uret(): kayit = [] for i, (ab, a) in enumerate(ABONE.items()): e = a["baslangic"] for d in DONEM: r = uretec(TOHUM + 101 * i + 7 * DONEM.index(d)) e += 4 + int(r() * 46) kayit.append({"abone": ab, "donem": d, "bolge": a["bolge"], "tip": a["tip"], "endeks": e, "birim": "m3"}) return kayit # ---- HAT: bes asama, her biri kendi dusurdugu satiri sayar def a1_ayikla(kayit): ZOR = ("abone", "donem", "bolge", "endeks", "birim") tut = [k for k in kayit if all(a in k for a in ZOR)] return tut, len(kayit) - len(tut) def a2_tekille(kayit): gor, tut = set(), [] for k in kayit: ad = (k["abone"], k["donem"]) if ad in gor: continue gor.add(ad) tut.append(k) return tut, len(kayit) - len(tut) def a3_tuketim(kayit): tablo = {(k["abone"], k["donem"]): k for k in kayit} cikti, dusen = [], 0 for k in kayit: i = DONEM.index(k["donem"]) if i == 0: continue onceki = tablo.get((k["abone"], DONEM[i - 1])) if onceki is None: dusen += 1 continue try: f = int(k["endeks"]) - int(onceki["endeks"]) except (TypeError, ValueError): dusen += 1 continue cikti.append(dict(k, m3=f)) return cikti, dusen def a4_ozet(kayit): top = {} for k in kayit: ad = (k["bolge"], k["donem"]) top[ad] = top.get(ad, 0) + k["m3"] return top, 0 def a5_sun(ozet): bolge = {} for (b, d), v in ozet.items(): bolge.setdefault(b, []).append(v) return {b: round(sum(v) / len(v), 2) for b, v in bolge.items()}, 0 ASAMA = [("ayikla", a1_ayikla), ("tekille", a2_tekille), ("tuketim", a3_tuketim), ("ozet", a4_ozet), ("sun", a5_sun)] def hat(kayit, asamalar=None): iz, veri = [], kayit for ad, f in (asamalar or ASAMA): veri, dusen = f(veri) iz.append({"asama": ad, "kalan": len(veri), "dusen": dusen}) return veri, iz # ---- VERI ALMA ve YENIDEN ISLEME def al(kayit, yukleme): """Veri alma asamasi: her yuke bir damga dusulur.""" return [dict(k, yukleme=yukleme) for k in kayit] def yeniden_ver(kayit, donemler, yukleme): """Duzeltilen yuk yeniden gonderiliyor ; damga degisir, deger degismez.""" return [dict(k, yukleme=yukleme) for k in kayit if k["donem"] in donemler] def depo_ekle(depo, yeni): """Yinelemeye DAYANIKSIZ yazma: gelen satir deponun sonuna eklenir.""" return depo + yeni def depo_anahtarla(depo, yeni): """Yinelemeye DAYANIKLI yazma: (abone , donem) anahtarinin uzerine yazilir.""" tablo = {(k["abone"], k["donem"]): k for k in depo} for k in yeni: tablo[(k["abone"], k["donem"])] = k return list(tablo.values()) def a2_tekille_tam(kayit): """KUSURLU TEKILLESTIRME: anahtara degil satirin tamamina bakar.""" gor, tut = set(), [] for k in kayit: im = tuple(sorted((a, str(v)) for a, v in k.items())) if im in gor: continue gor.add(im) tut.append(k) return tut, len(kayit) - len(tut) KUSURLU = [("ayikla", a1_ayikla), ("tekille", a2_tekille_tam), ("tuketim", a3_tuketim), ("ozet", a4_ozet), ("sun", a5_sun)] def d_tekillik(veri): return len(veri) != len(set((k["abone"], k["donem"]) for k in veri)) def d_satir_sayisi(veri, beklenen=2400, pay=0.05): return abs(len(veri) - beklenen) / beklenen > pay
Çoğalan Satır ve Değişmeyen Sunum
İkinci blok beş kurulumu aynı kaynağa uygular. ham sütunu depodaki satır sayısını, tekille o
aşamanın düşürdüğü satırı, ozet dördüncü aşamanın hücre sayısını, kuzey sunulan beş değerden
birini verir.
KAYNAK_KAYIT = kaynak_uret() ILK = al(KAYNAK_KAYIT, 1) TABAN, _ = hat(ILK) def yaz(ad, depo, asamalar=None): sunum, iz = hat(depo, asamalar) print(f"{ad:<30}{len(depo):>6}{iz[1]['dusen']:>9}{iz[3]['kalan']:>6}" f"{sunum['kuzey']:>11.2f}{'ayni' if sunum == TABAN else 'degisti':>9}") bir_donem = yeniden_ver(KAYNAK_KAYIT, {"2026-07"}, 2) tam = yeniden_ver(KAYNAK_KAYIT, set(DONEM), 2) print("taban sunum:", TABAN) print("yeniden verilen satir: bir donem", len(bir_donem), " tam kosum", len(tam)) print() print(f"{'kurulum':<30}{'ham':>6}{'tekille':>9}{'ozet':>6}{'kuzey':>11}{'sunum':>9}") yaz("tek kosum", ILK) yaz("ekleyen depo , bir donem", depo_ekle(ILK, bir_donem)) yaz("ekleyen depo , tam kosum", depo_ekle(ILK, tam)) yaz("anahtarlayan depo , tam kosum", depo_anahtarla(ILK, tam)) yaz("kusurlu tekillestirme , tam", depo_ekle(ILK, tam), KUSURLU) print() d = depo_ekle(ILK, tam) print("tekillik denetimi:", d_tekillik(d), " satir sayisi denetimi:", d_satir_sayisi(d))
taban sunum: {'merkez': 1321.45, 'kuzey': 1212.55, 'dogu': 881.36, 'bati': 833.09, 'guney': 1065.55}
yeniden verilen satir: bir donem 200 tam kosum 2400
kurulum ham tekille ozet kuzey sunum
tek kosum 2400 0 55 1212.55 ayni
ekleyen depo , bir donem 2600 200 55 1212.55 ayni
ekleyen depo , tam kosum 4800 2400 55 1212.55 ayni
anahtarlayan depo , tam kosum 2400 0 55 1212.55 ayni
kusurlu tekillestirme , tam 4800 0 55 2425.09 degisti
tekillik denetimi: True satir sayisi denetimi: True
İkinci satır dersin başlığıdır: bir dönem geri doldurulduğunda ekleyen depo 2600 satır taşıyor, yani 200 satır çoğaldı. Tekilleştirme aşaması tam olarak o 200 satırı düşürüyor ve sunulan değer 1212,55’te kalıyor. Üçüncü satır aynı şeyi büyük ölçekte gösterir: tam yeniden koşum deposu 4800 satıra çıkarıyor, tekilleştirme 2400 satır düşürüyor, sunum yine aynı.
Bu, kursun üçüncü iddiasının en temiz örneğidir. Deponun boyutu iki katına çıkmış, hat aynı işi iki kez yapmış, ama sunulan beş değerin hiçbiri kımıldamamıştır. Çıktıya bakan bir gözlem hattın yinelemeye dayanıklı olduğunu düşünür. Oysa dayanıklı olan hat değil, hattın içindeki tek bir aşamadır: tekilleştirme fazlalığı yutuyor ve yutarken kimseye haber vermiyor.
Dördüncü satır gerçek dayanıklılığın ne olduğunu gösterir. Anahtarlayan depo ikinci koşumdan sonra da 2400 satır taşıyor: çoğalan satır 0, tekilleştirmenin düşürdüğü satır 0. Fark depoda değil, hattın ötesindedir; ekleyen depo doğru sayıyı üretirken iki kat yer tutar ve tekilleştirme aşaması olmadan kullanılamaz.
Son iki satır denetimin ne dediğidir. Tekillik denetimi ekleyen depoda ateşliyor, satır sayısı denetimi de ateşliyor — 4800, beklenen 2400’ün yüzde beşlik bandının çok dışındadır. Yani bozulmanın yakalama gecikmesi 0’dır ve bunu yakalayan denetim sunuma bakan denetim değildir.
Yutulan Düzeltme
Buraya kadar yeniden verilen satırın değeri ilkiyle aynıydı, bu yüzden tekilleştirmenin hangisini tuttuğu önemsizdi. Gerçek geri doldurmalarda durum tersidir: yük düzeltildiği için yeniden gönderilir. Tekilleştirme aşaması ilk gördüğü satırı tutar, yani eskisini. Aşağıdaki kurulumda üretici son dönemi eksik okumuş, sonra düzeltip yeniden göndermiştir. Bozulmanın son döneme konması bilinçlidir: dizinin ortasındaki bir kayma izleyen dönemde ters işaretle geri gelir ve ortalamada birbirini götürür.
def eksik_okuma(kayit, donem="2026-12", fark=100): """Uretici son donemi eksik okudu ; sonra duzeltip yeniden gonderecek.""" return [dict(k, endeks=k["endeks"] - fark) if k["donem"] == donem else k for k in kayit] EKSIK = al(eksik_okuma(KAYNAK_KAYIT), 1) DUZELTME = yeniden_ver(KAYNAK_KAYIT, {"2026-12"}, 2) print("duzeltilmis satir:", len(DUZELTME)) print(f"{'kurulum':<32}{'ham':>6}{'tekille':>9}{'kuzey':>10}{'taban':>10}") for ad, depo in (("eksik yuk , duzeltme yok", EKSIK), ("ekleyen depo , duzeltme geldi", depo_ekle(EKSIK, DUZELTME)), ("anahtarlayan depo , duzeltme", depo_anahtarla(EKSIK, DUZELTME))): sunum, iz = hat(depo) print(f"{ad:<32}{len(depo):>6}{iz[1]['dusen']:>9}{sunum['kuzey']:>10.2f}" f"{TABAN['kuzey']:>10.2f}")
duzeltilmis satir: 200 kurulum ham tekille kuzey taban eksik yuk , duzeltme yok 2400 0 794.36 1212.55 ekleyen depo , duzeltme geldi 2600 200 794.36 1212.55 anahtarlayan depo , duzeltme 2400 0 1212.55 1212.55
İkinci satır dersin en pahalı bulgusudur. Düzeltme hatta geldi, 200 satır yeniden işlendi, depo 2600 satıra çıktı, tekilleştirme 200 satır düşürdü — ve sunulan değer 794,36’da kaldı, yani düzeltme öncesiyle birebir aynı. Düşürülen 200 satır düzeltilmiş olanlardı. Tekilleştirme aşaması ikinci koşumu yuttu; burada yutmak kaybetmektir.
Bu, önceki bölümün tam tersi bir okumadır ve ikisi aynı davranıştan çıkar. Yeniden verilen satır ilkiyle aynı olduğunda tekilleştirme hattı kurtarıyor; düzeltilmiş olduğunda aynı tekilleştirme düzeltmeyi çöpe atıyor. Aşama ikisini ayırt edemez, çünkü elinde yalnızca anahtar vardır ve iki satırın anahtarı aynıdır. Üçüncü satır çözümü gösterir: anahtarlayan depo yeni satırı eskisinin üzerine yazdığı için sunum 1212,55’e, yani tabana döner.
Bir hattın yinelemeye dayanıklı sayılması için aynı yükün iki kez işlenmesinin sonucu değiştirmemesi yetmez; düzeltilmiş bir yükün ikinci kez işlenmesinin sonucu düzeltmesi de gerekir. Ekleyen depo birinci koşulu sağlıyor, ikincisini sağlamıyor.
Anahtar Yanlış Seçildiğinde
Tablonun son satırı hattın en kırılgan varsayımını açar. Tekilleştirme aşaması (abone, donem)
anahtarına bakar. Aynı aşama satırın tamamına bakacak biçimde yazılsaydı, yeniden verilen satır
yükleme damgası yüzünden farklı görünür ve elenmezdi. Bu, uydurma bir kusur değildir: bir yükün
tümüyle aynı olup olmadığını sormak sezgisel olarak daha güvenli görünür ve tam da bu yüzden yazılır.
ekleyen, anahtarlayan = ILK, ILK print(f"{'kosum':<6}{'ekleyen ham':>12}{'kuzey':>9}{'kusurlu kuzey':>15}" f"{'anahtarlayan ham':>18}{'kuzey':>9}") for kosum in range(1, 4): if kosum > 1: yeni = yeniden_ver(KAYNAK_KAYIT, set(DONEM), kosum) ekleyen = depo_ekle(ekleyen, yeni) anahtarlayan = depo_anahtarla(anahtarlayan, yeni) sun_ekle, _ = hat(ekleyen) sun_kusur, _ = hat(ekleyen, KUSURLU) sun_anahtar, _ = hat(anahtarlayan) print(f"{kosum:<6}{len(ekleyen):>12}{sun_ekle['kuzey']:>9.2f}" f"{sun_kusur['kuzey']:>15.2f}{len(anahtarlayan):>18}" f"{sun_anahtar['kuzey']:>9.2f}") print() oz, _ = a4_ozet(a3_tuketim(a2_tekille_tam(a1_ayikla(ekleyen)[0])[0])[0]) ozt, _ = a4_ozet(a3_tuketim(a2_tekille(a1_ayikla(ILK)[0])[0])[0]) print("ozet ('kuzey', '2026-07') taban:", ozt[("kuzey", "2026-07")], " kusurlu tekillestirme:", oz[("kuzey", "2026-07")]) print("tekillestirmenin tuttugu anahtar:", len(set((k["abone"], k["donem"]) for k in ILK)))
kosum ekleyen ham kuzey kusurlu kuzey anahtarlayan ham kuzey
1 2400 1212.55 1212.55 2400 1212.55
2 4800 1212.55 2425.09 2400 1212.55
3 7200 1212.55 3637.64 2400 1212.55
ozet ('kuzey', '2026-07') taban: 1251 kusurlu tekillestirme: 3753
tekillestirmenin tuttugu anahtar: 2400
Üç koşumluk tablo iki cümleyi yan yana koyar. Doğru anahtarla çalışan hatta ham depo 2400’den
4800’e, 7200’e çıkıyor ve sunulan değer üç koşumda da 1212,55. Kusurlu anahtarla çalışan hatta
aynı ham depo, aynı yeniden koşumlar, ama sunulan değer 1212,55 → 2425,09 → 3637,64 diye
büyüyor: koşum sayısıyla doğru orantılı. Özet katmanında aynı şey görünür, kuzeyin 2026-07 hücresi
tabanda 1251 iken üçüncü koşumdan sonra 3753’tür.
İki hat arasındaki tek fark bir aşamanın anahtar seçimidir. Hiçbir bozulma sınıfı yok, hiçbir alan adı değişmedi, hiçbir tür kaymadı; üretici tarafında olan tek şey aynı doğru yükün ikinci kez gönderilmesidir. Bu, kursun ikinci iddiasının bu derse düşen biçimidir: hattın kendi aşaması, kusurlu bir anahtarla, hiçbir kaynak bozulması olmadan sunulan sayıyı üç katına çıkarabilir.
Anahtarlayan deponun sütunu bedelin nerede durduğunu söyler. Yinelemeye dayanıklılık ücretsiz değildir: yazma anında 2400 girişlik bir anahtar tablosu tutulur ve her satır yazılmadan önce aranır. Tekilleştirme aşaması da aynı büyüklükte bir küme taşır. Bunun karşılığında depo koşum sayısından bağımsız olarak 2400 satırda kalır ve hattın doğruluğu tek bir aşamanın anahtarına bağımlı olmaktan çıkar.
Özet
- Yeniden işleme sıradan bir iştir; ekleyen depoda bir dönemin geri doldurulması ham satırı 2400’den 2600’e, tam yeniden koşum 4800’e, üçüncü koşum 7200’e çıkarır.
- Sunulan beş değer bu büyümenin hiçbirini göstermez: kuzey üç koşumda da 1212,55’tir, çünkü tekilleştirme aşaması fazlalığı yutar ve yutarken haber vermez.
- Yinelemeye dayanıklı olan hat değil, hattın içindeki tek bir aşamadır; anahtarlayan yazma kullanıldığında çoğalan satır 0’a iner ve depo koşum sayısından bağımsız kalır.
- Yeniden verilen yük bir düzeltme taşıdığında aynı tekilleştirme onu çöpe atar: sunulan değer 794,36’da kalır, oysa anahtarlayan depo aynı düzeltmeyle 1212,55’e döner. Dayanıklılık, ikinci koşumun sonucu değiştirmemesi değil, düzeltmesi gerektiğinde düzeltmesidir.
- Tekilleştirme
(abone, donem)yerine satırın tamamına baktığında aynı yeniden koşumlar sunulan değeri 1212,55’ten 2425,09’a, sonra 3637,64’e taşır; özet hücresi 1251’den 3753’e çıkar. - Çoğalmayı yakalayan denetimler tekillik ile satır sayısıdır ve ikisi de aşama 0’da ateşler; sunuma bakan hiçbir denetim bunu göremez.
Sonraki Adım
Üç derste denetim hep aynı yere baktı: satırın kendisine. Alanları var mı, türü doğru mu, anahtarı benzersiz mi, değeri önceki dönemlerin düzeninde mi. Bu sorular bir sunum değeri bozulduğunda yanıt vermez, çünkü hiçbiri satırın nereden geldiğini söylemez. Kusurlu tekilleştirmeyle üretilen 3753 rakamına bakan biri, o hücreye hangi yüklerin katkı verdiğini ve zincirin hangi halkasında hata olduğunu bulmak için hattın tamamını baştan okumak zorundadır. Sonraki ders bu aramayı sayar: bozulmuş bir sunum değerinden kaynağa gitmek için kaç aşamaya ve kaç satıra bakmak gerekiyor, kayıt tutulduğunda ve tutulmadığında.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.