Ders 03 / 16
Mesaj Sistemleri
Bölüm sayısının tüketici grubuna dağıttığı iş ile bölüm başına sıra korunumunun yan yana sayılması: dört tüketicili bir grupta tek bölüm üç tüketiciyi boşta bırakıyor, dört bölüm hepsini çalıştırıyor. Abone anahtarıyla bölümlenen konuda hiçbir abone dağılmıyor ve tüketim her bölüm sayısında 2200 satır kalıyor, ama yük 708 ile 492 arasında eğriliyor. En dengeli anahtar olan kayıt anahtarı yükü 621 ile 583 arasına sıkıştırıyor ve 200 abonenin hepsini dağıtıyor: tüketim dört bölümde 527 satıra düşüyor, sunum her bölgede 616 ile 977 arasında kayıyor. Dönem anahtarı ise 2200 satırın 2000'ini kaybederken sunumu yalnız −15,29 ile +16,15 arasında oynatıyor.
İçindekiler
Önceki iki ders alma işini çekme üzerinden ele aldı: hat kaynağa gitti, ne isteyeceğine kendi karar verdi ve kotasını kendi harcadı. Kaynağın veriyi kendiliğinden ittiği düzenek bu dengeyi tersine çevirir. Kayıtlar bir konuya (topic) yazılır, konu bölümlere ayrılır ve bölümleri bir tüketici grubu (consumer group) okur. Kuyruk, yayımla–abone ol düzeni, konum ve teslim semantiği Önbellekleme, Kuyruklar ve Eşzamansız İşleme kursunda ölçüldü; yordam burada tekrarlanmaz.
Bu dersin ölçüsü iki sayıdır: bölüm sayısının tüketiciye dağıttığı iş ve bölüm başına sıra korunumu. İkisi aynı ayarın iki yüzüdür. Bölüm sayısı arttıkça paralellik artar; ama aynı abonenin kayıtları farklı bölümlere düştüğünde, tüketim hesabının dayandığı sıra kırılır ve hat satır kaybeder.
- VA17. Kod kurgudur; gerçek bir mesaj sistemi, akış işleyici ya da orkestratör çağrılmaz. Kaynak yine 200 abone, 12 dönem, 2400 satır, tohum 20260218.
- VA18. Konuya yazım sırası dönem dönemdir; bir dönemin bütün abone kayıtları yazıldıktan sonra sonraki dönem başlar.
- VA19. Bir kayıt bölüm anahtarına göre tek bir bölüme düşer ve aynı anahtar her zaman aynı bölüme gider. Bölüm içindeki konum (offset) yazım sırasını korur; bölümler arasında böyle bir sıra yoktur.
- VA20. Bir bölümü grup içinde tek bir tüketici okur. Bölüm sayısı bu yüzden aynı gruptaki etkin tüketici sayısının tavanıdır. Grupta dört tüketici vardır.
- VA21. Üç bölüm anahtarı sınanır:
abone,kayit(abone ile dönemin birleşimi) vedonem. Üçü de kaynağın kendi alanlarıdır; hiçbiri uydurma değildir. - VA22. Her tüketici tüketim hesabını yalnız kendi bölümündeki kayıtlarla yapar; bir abonenin önceki dönemi başka bir bölümdeyse o satır hesaplanamaz ve düşer.
- VA23. Taban çizgisi orkestrasyonsuz koşumdur; sağlam hatta tüketim 2200 satırdır ve sunum sapması boştur.
- VA24. Bölüm sayısı ve boşta tüketici tam sayıdır, oran basılmaz. Satır oranının adımı 1/2400, yani 0,0004; sunum üzerinde oran basılmaz.
Konu, Bölüm ve Tüketici Grubu
Aşağıdaki blok ortak tanımı kurar ve üzerine bölümlü bir konu ile onu okuyan bir tüketici grubu ekler. Her kurulum için beş sayı basılıyor: en çok ve en az yüklenen tüketicinin satır sayısı, boşta kalan tüketici sayısı, birden çok bölüme dağılmış abone sayısı ve bölümlerden toplanan tüketim satırı.
# KURGUDUR. Gercek bir mesaj sistemi, akis isleyici ya da orkestrator # cagrilmaz; olcum aginin sayac okumalari kurgudur, tohum 20260218. 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(): # her donem her abone icin bir okuma 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 asama 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 basina donem ortalamasi 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 def okuma_sonucu(kayitlar): v, _ = a1_ayikla(kayitlar) v, _ = a2_tekille(v) v, _ = a3_tuketim(v) oz, _ = a4_ozet(v) sun, _ = a5_sun(oz) return sun, len(v) # ---- KURGU konu: bolumler , bolum anahtari , tuketici grubu. def dagit(anahtar, p): """Anahtardan bolum numarasi. Ayni anahtar her zaman ayni bolume duser.""" x = 0 for c in anahtar: x = (x * 131 + ord(c)) & M32 return int(uretec(TOHUM + x)() * p) def bolumle(kayitlar, p, anahtar): """Konuya yazim sirasi donem donem ; her kayit anahtarina gore bir bolume yazilir. Bolum icindeki konum yazim sirasini korur.""" bolum = {b: [] for b in range(p)} for k in sorted(kayitlar, key=lambda k: (k["donem"], k["abone"])): ad = {"abone": k["abone"], "kayit": k["abone"] + k["donem"], "donem": k["donem"]}[anahtar] b = dagit(ad, p) bolum[b].append(dict(k, konum=len(bolum[b]))) return bolum def tuketici_grubu(bolum, c): """Bir bolumu grup icinde tek bir tuketici okur ; bolum sayisi tavandir.""" atama = {t: [] for t in range(c)} for b in bolum: atama[b % c].append(b) return atama ham = kaynak_uret() dogru_sun, dogru_n = okuma_sonucu(ham) print("tuketici grubu 4 tuketici , tuketim saglam hatta", dogru_n, "satir") print("anahtar bolum en cok en az bosta dagilan abone hesaplanan tuketim") for anahtar in ("abone", "kayit", "donem"): for p in (1, 2, 4, 8): bl = bolumle(ham, p, anahtar) at = tuketici_grubu(bl, 4) yuk = [sum(len(bl[b]) for b in at[t]) for t in at] yer = {} for b in bl: for k in bl[b]: yer.setdefault(k["abone"], set()).add(b) tk = sum(len(a3_tuketim(bl[b])[0]) for b in bl) print(f"{anahtar:<8} {p:>6} {max(yuk):>7} {min(yuk):>6} " f"{sum(1 for y in yuk if y == 0):>6} " f"{sum(1 for v in yer.values() if len(v) > 1):>14} {tk:>19}")
tuketici grubu 4 tuketici , tuketim saglam hatta 2200 satir anahtar bolum en cok en az bosta dagilan abone hesaplanan tuketim abone 1 2400 0 3 0 2200 abone 2 1200 0 2 0 2200 abone 4 708 492 0 0 2200 abone 8 696 528 0 0 2200 kayit 1 2400 0 3 0 2200 kayit 2 1211 0 2 200 1076 kayit 4 621 583 0 200 527 kayit 8 624 572 0 200 268 donem 1 2400 0 3 0 2200 donem 2 1600 0 2 200 1000 donem 4 800 400 0 200 200 donem 8 1000 200 0 200 200
Bölüm Sayısının Dağıttığı İş
İlk sütun çifti anahtardan bağımsız bir gerçeği yazıyor: tek bölümlü bir konuda dört tüketicinin üçü boşta durur, iki bölümde ikisi boşta durur, dörde çıkıldığında hiçbiri boşta kalmaz. Bölüm sayısı bir tercih değil bir tavandır; gruba tüketici eklemek bölüm sayısını aşan noktada hiçbir şey kazandırmaz. Sekiz bölümde de dört tüketici çalışır, ama her biri iki bölüm okur.
İkinci gözlem yükün nasıl bölündüğüdür. Abone anahtarında dört bölüm 708 ile 492 satır arasında eğriliyor, yani en yüklü tüketici en boş olanın 1,44 katı iş yapıyor. Kayıt anahtarında aynı kurulum 621 ile 583 arasına sıkışıyor: bu üç anahtarın en dengelisidir, çünkü abone ile dönemi birleştiren anahtar 2400 farklı değer üretir ve bölümlere neredeyse eşit yayılır. Dönem anahtarı en kötüsüdür; on iki farklı değeri dört bölüme dağıtınca yük 800 ile 400 arasında, sekiz bölümde 1000 ile 200 arasında açılır. Yalnız bu üç satıra bakan biri kayıt anahtarını seçerdi.
Bölüm Başına Sıra Korunumu
Son iki sütun seçimi tersine çeviriyor. Abone anahtarında hiçbir abone dağılmıyor ve tüketim her bölüm sayısında 2200 satır kalıyor. Kayıt anahtarında 200 abonenin hepsi dağılıyor ve tüketim dört bölümde 527, sekiz bölümde 268 satıra iniyor. Mekanizma tek cümledir: bir bölüm kendi içinde sırayı korur, bölümler arasında sıra yoktur, ve tüketim bir abonenin ardışık iki döneminin farkıdır. İki dönem farklı bölümlere düşerse o satırı hesaplayacak tüketici yoktur.
print("anahtar bolum hesaplanan tuketim sunum sapmasi") for anahtar, p in (("abone", 4), ("kayit", 4), ("donem", 2), ("donem", 4)): bl = bolumle(ham, p, anahtar) oz, tk = {}, 0 for b in bl: # her tuketici kendi bolumunu okur v, _ = a3_tuketim(bl[b]) tk += len(v) o, _ = a4_ozet(v) for ad, s in o.items(): oz[ad] = oz.get(ad, 0) + s s, _ = a5_sun(oz) print(f"{anahtar:<8} {p:>6} {tk:>18} ", {b: round(s.get(b, 0) - dogru_sun[b], 2) for b in dogru_sun}) bl = bolumle(ham, 4, "abone") print() print("abone anahtarli bolum 0 :", len(bl[0]), "kayit , son konum", bl[0][-1]["konum"]) print("ilk uc kayit :", [(k["abone"], k["donem"], k["konum"]) for k in bl[0][:3]]) ab = bl[0][0]["abone"] print(ab, "kayitlarinin bolumleri :", sorted(set(b for b in bl for k in bl[b] if k["abone"] == ab))) kl = bolumle(ham, 4, "kayit") print(ab, "kayit anahtarinda :", sorted(set(b for b in kl for k in kl[b] if k["abone"] == ab)))
anahtar bolum hesaplanan tuketim sunum sapmasi
abone 4 2200 {'merkez': 0.0, 'kuzey': 0.0, 'dogu': 0.0, 'bati': 0.0, 'guney': 0.0}
kayit 4 527 {'merkez': -977.27, 'kuzey': -960.55, 'dogu': -686.91, 'bati': -616.0, 'guney': -801.1}
donem 2 1000 {'merkez': 16.15, 'kuzey': -7.35, 'dogu': 12.84, 'bati': -15.29, 'guney': 4.65}
donem 4 200 {'merkez': 180.55, 'kuzey': 57.45, 'dogu': 124.64, 'bati': -24.09, 'guney': 25.45}
abone anahtarli bolum 0 : 492 kayit , son konum 491
ilk uc kayit : [('A005', '2026-01', 0), ('A007', '2026-01', 1), ('A014', '2026-01', 2)]
A005 kayitlarinin bolumleri : [0]
A005 kayit anahtarinda : [0, 1, 2, 3]
Son dört satır düzeneği tek bir abone üzerinde gösteriyor. Abone anahtarında A005’in on iki kaydının hepsi bölüm 0’dadır ve o bölümü okuyan tüketici on ikisini de sırayla görür. Kayıt anahtarında aynı abonenin kayıtları dört bölüme birden dağılmıştır; hiçbir tüketici o abonenin ardışık iki dönemini birlikte görmez. Bölümün içindeki konum kusursuz artmaya devam eder — bölüm 0 kendi 492 kaydını 0’dan 491’e sıralar. Sıra bozulmamıştır; yanlış yerde korunmuştur.
Konumun ikinci işi kursun kuralına dokunur. Bir tüketici grubu bölüm başına tek bir sayı tutar: o bölümde nereye kadar okuduğunu. Grup düştüğünde ya da yeniden kurulduğunda okumaya o konumdan devam eder, ve konum geriye alındığında aynı kayıtlar yeniden okunur. Alma adımının yeniden koşturulabilir olmasının dayanağı budur; çekmeli bir bağlayıcıda aynı şeyi yapabilmek için kaynağın eski satırları hâlâ veriyor olması gerekir. Bölüm 0’ın son konumu 491 olduğuna göre o bölümü baştan okumak 492 kaydı yeniden getirir, ve hedef yazımı yinelemeye dayanıklı olduğu sürece ikinci koşum ilkiyle aynı sonucu verir.
Buradan çıkan kural, en dengeli anahtarın en yanlış anahtar olabileceğidir. Bölüm anahtarı bir yük dağıtma ayarı gibi görünür, oysa tüketicinin hangi kayıtları birlikte görebileceğini belirler. Doğru anahtar, hesabın gruplama alanıdır: tüketim abone başına hesaplandığı için anahtar abone olmalıdır. Bunun bedeli 1,44 katlık yük eğriliğidir ve 2200 satırın tamamı karşılığında ucuzdur.
Sunulan Sayının Yanıltması
Dönem anahtarının iki satırı dersin en sessiz sonucudur. İki bölümde tüketim 2200’den 1000 satıra düşüyor, yani 1200 satır kayboluyor, ama sunum sapması −15,29 ile +16,15 arasında kalıyor: bin küsur birimlik değerler üzerinde yüzde ikiye bile varmayan bir oynama. Kayıt anahtarının dört bölümlü kurulumu ise daha az satır kaybediyor gibi durmaz — 527 satırla daha fazla kaybeder — ve sunumu −616 ile −977 arasında yıkar.
Fark kayıp miktarında değil kaybın şeklindedir. Özet katmanı her bölge ve dönem çifti için toplam alır, sunum katmanı bu toplamların dönem ortalamasını alır. Dönem anahtarı bütün bir dönemi birden düşürür: o dönemin hücresi hiç oluşmaz ve ortalama kalan dönemler üzerinden alınır, her biri kendi içinde doğrudur. Kayıt anahtarı ise her dönemin içinden rastgele satır düşürür: hücreler oluşur ama eksik toplarlar ve ortalama topluca aşağı iner. Aynı düzeneğin daha büyük kaybı daha küçük bir sapma üretebilir. Bir bölümleme kararının doğruluğu sunulan sayıya bakarak ölçülemez; ölçüsü hesaplanan tüketim satırıdır.
Özet
- Bölüm sayısı aynı gruptaki etkin tüketici sayısının tavanıdır: tek bölümde dört tüketicinin üçü, iki bölümde ikisi boşta kalır; dört bölümde hepsi çalışır.
- Bölüm anahtarı bir yük dağıtma ayarı değil, tüketicinin hangi kayıtları birlikte görebileceğini belirleyen bir karardır. Bölüm kendi içinde sırayı korur, bölümler arasında sıra yoktur.
- Abone anahtarı hiçbir aboneyi dağıtmaz ve tüketimi her bölüm sayısında 2200 satırda tutar; bedeli 708 ile 492 arasında, yani 1,44 katlık bir yük eğriliğidir.
- En dengeli anahtar en yanlış anahtar olabilir: kayıt anahtarı yükü 621 ile 583 arasına sıkıştırır ama 200 abonenin hepsini dağıtır ve dört bölümde tüketimi 527 satıra indirir.
- Dönem anahtarı 2200 satırın 2000’ini kaybederken sunumu yalnız −15,29 ile +16,15 arasında oynatır, çünkü tam dönem düşürmek ortalamayı bozmaz. Bölümleme kararının ölçüsü sunulan sayı değil hesaplanan tüketim satırıdır.
Sonraki Adım
Bu üç derste veri hatta alındı: yöntem seçildi, kaynağın kısıtı sayıldı, konu bölümlendi ve tüketici grubuna dağıtıldı. Her üçünde de dönem kapalı bir kutu gibi ele alındı — bir dönemin bütün kayıtları o dönem işlenirken elde sayıldı. Bir kayıt kendi dönemi kapandıktan sonra gelebilir, ve o zaman sonucu hangi pencerenin sahipleneceği bir karar hâline gelir. Sonraki ders akış işlemeyi bu soruyla ölçer: pencere kararı geç gelen kayıtta sonucu nasıl değiştiriyor ve pencereler arasında durum taşımanın bedeli nedir. Kalan derslerin ortak sorusu ise burada hiç sorulmadı: veri hatta alınırken kaybolup kaybolmadığı.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.