---
title: 'Durum Bölme'
source: 'https://academia.sh/tr/kurslar/kod-olarak-altyapi/durum-bolme'
course: 'Kod Olarak Altyapı'
language: tr
updated: '2026-08-17T18:09:07+00:00'
license: 'CC BY-SA 4.0'
---

# Durum Bölme

Tek durumda büyüyen altyapının plan süresi ve etki yarıçapı, aynı ölçümlerin bölünmüş hâli, bölmenin bedeli olan parçalar arası bağımlılıkların sayısı, çıktı okuma ile veri kaynağının farkı ve bir parça değiştiğinde yeniden uygulanan parça sayısı.

Kilit doğruluğu kurtardı ama sırayı da kurdu: aynı durum dosyasına yazan herkes bekliyor. Kilidin
kapsadığı alanı küçültmenin tek yolu durumu bölmektir. Bu ders bölmeden önceki ve sonraki
sayıları yan yana koyar, sonra bölmenin faturasını çıkarır.

## Tek Durumda Büyüyen Altyapı

Kurgu ölçüm ağı bir yıl içinde büyüdü. **DM13.** Model on üç parçaya ayrılabilecek bir yapı
kuruyor: üç ortamın her birinde ağ, veri, hesaplama ve gözlem katmanları, bir de üç ortamın
ortaklaşa kullandığı bölge omurgası.

```js
// ag-uret.mjs — buyumus bolgesel olcum agi: on uc parca, kalemler ve bagimlilik kenarlari.
// Cikti iki bicimde yazilir: tek durum dosyasi ve parca basina birer durum dosyasi.
import { writeFileSync, mkdirSync, rmSync } from "node:fs";

const ortamlar = ["deneme", "hazirlik", "uretim"];
const katmanlar = ["ag", "veri", "hesaplama", "gozlem"];
const parcalar = [{ ad: "ortak", katman: "ortak", adet: 20 }];
for (const o of ortamlar)
  for (const k of katmanlar) parcalar.push({ ad: `${o}_${k}`, ortam: o, katman: k, adet: 50 });

// Katmanin baska katmanlardan kac kalem uzerinden bilgi aldigi.
const disBagimlilik = {
  ag: [["ortak", 2]], veri: [["ag", 3]],
  hesaplama: [["ag", 6], ["veri", 4]], gozlem: [["hesaplama", 5], ["veri", 2]],
};
const hedefParca = (p, katman) => (katman === "ortak" ? "ortak" : `${p.ortam}_${katman}`);

const kalemler = [], icKenar = [], disKenar = [];
for (const p of parcalar) {
  for (let i = 0; i < p.adet; i++) {
    kalemler.push({ ad: `${p.ad}/k${i}`, parca: p.ad });
    if (i > 0) icKenar.push([`${p.ad}/k${i}`, `${p.ad}/k${i - 1}`]);
  }
  for (const [katman, adet] of disBagimlilik[p.katman] ?? [])
    for (let i = 0; i < adet; i++)
      disKenar.push([`${p.ad}/k${i}`, `${hedefParca(p, katman)}/k${i}`]);
}

rmSync("bolunmus", { recursive: true, force: true });
mkdirSync("bolunmus");
const kalem = (k) => ({ ...k, bagimli: [...icKenar, ...disKenar].filter((e) => e[0] === k.ad).map((e) => e[1]) });
writeFileSync("tek-durum.json", JSON.stringify({ seri: 1, kalemler: kalemler.map(kalem) }));
for (const p of parcalar)
  writeFileSync(`bolunmus/${p.ad}.json`, JSON.stringify(
    { seri: 1, kalemler: kalemler.filter((k) => k.parca === p.ad).map(kalem) }));

// Saglayicidaki gercek: kayittaki kalemler ve uretim hesaplama katmanindaki uc kayit disi kaynak.
const saglayici = [...kalemler.map((k) => k.ad),
  "uretim_hesaplama/elle-1", "uretim_hesaplama/elle-2", "uretim_hesaplama/elle-3"];
writeFileSync("saglayici.json", JSON.stringify(saglayici));

console.log(`parca: ${parcalar.length}, kalem: ${kalemler.length}, ` +
  `parca ici kenar: ${icKenar.length}, parcalar arasi kenar: ${disKenar.length}`);
console.log(`tek durum dosyasi: 1 x ${kalemler.length} kalem | bolunmus: ` +
  `${parcalar.length} dosya, en buyugu ${Math.max(...parcalar.map((p) => p.adet))} kalem`);
console.log(`saglayicida ${saglayici.length} kaynak, kayitta ${kalemler.length} ` +
  `-> kayit disi ${saglayici.length - kalemler.length}`);
```

```
parca: 13, kalem: 620, parca ici kenar: 607, parcalar arasi kenar: 66
tek durum dosyasi: 1 x 620 kalem | bolunmus: 13 dosya, en buyugu 50 kalem
saglayicida 623 kaynak, kayitta 620 -> kayit disi 3
```

Altı yüz yirmi kalem, altı yüz yetmiş üç kenar. Kenarların yalnız altmış altısı parça sınırını
geçiyor — geri kalanı parçaların içinde kalıyor. Bu oran bölmenin neden mümkün olduğunu
söylüyor: bağların yüzde doksanı zaten yereldir.

Son satır bu dersin boyunca sabit kalacak bir farkı kuruyor: sağlayıcıda altı yüz yirmi üç
kaynak var, kayıtta altı yüz yirmi. Üç kaynak hiçbir parçanın durumunda değil. Bölme bu sayıyı
değiştirmez — kaydın kapsamadığı altyapı, kayıt kaç dosyaya bölünürse bölünsün kapsam dışında
kalır. Aşağıda göreceği tek etki, hangi bağlanma biçiminin o üç kalemi yanlışlıkla içeri
aldığıdır.

## Plan Süresi ve Etki Yarıçapı

Plan, kayıttaki her kalemi sağlayıcıdan tazeleyip tanımla karşılaştırır. **DM14.** Kalem başına
bir tazeleme okuması bir milisaniye sürüyor; gerçek süre sağlayıcıya ve ağ gecikmesine bağlıdır,
ama kalem sayısıyla doğrusal olduğu değişmez.

Ölçüm kuralı önceki dersteki ile aynı: ölçülen süre basılmaz, beklenenin 0,7 ile 2,0 katı
arasında olup olmadığı basılır.

```js
// plan.mjs — verilen kapsamin durumunu okur, her kalemi tazeler ve plan suresini olcer.
// Basilan degerler kosumdan bagimsizdir: tazeleme sayisi ile ondan turetilen beklenen sure,
// bir de olculen surenin bant denetimi. Ham milisaniye basilmaz.
// kullanim: node plan.mjs tek | node plan.mjs parca <ad>
import { readFileSync } from "node:fs";
const OKUMA_MS = 1, ALT = 0.7, UST = 2.0;        // tazeleme okumasinin modellenen maliyeti ve bant
const bekle = (ms) => { const b = Date.now() + ms; while (Date.now() < b); };
const [kapsam, ad] = [process.argv[2] ?? "tek", process.argv[3]];
const dosya = kapsam === "tek" ? "tek-durum.json" : `bolunmus/${ad}.json`;

const t0 = Date.now();
const d = JSON.parse(readFileSync(dosya, "utf8"));
for (const k of d.kalemler) bekle(OKUMA_MS);     // kalem basina bir tazeleme okumasi
const olculen = Date.now() - t0;
const beklenen = d.kalemler.length * OKUMA_MS;

console.log(`${(kapsam === "tek" ? "tek durum" : ad).padEnd(13)} | ` +
  `${String(d.kalemler.length).padStart(3)} tazeleme, beklenen plan ${String(beklenen).padStart(3)} ms | ` +
  `olculen bantta: ${olculen >= ALT * beklenen && olculen <= UST * beklenen ? "evet" : "hayir"} | ` +
  `kilitlenen kalem ${String(d.kalemler.length).padStart(3)}`);
```

İki kapsamda da yapılan iş aynıdır: gözlem katmanındaki tek bir kalemi değiştirmek.

```sh
node plan.mjs tek
node plan.mjs parca uretim_gozlem
```

```
tek durum     | 620 tazeleme, beklenen plan 620 ms | olculen bantta: evet | kilitlenen kalem 620
uretim_gozlem |  50 tazeleme, beklenen plan  50 ms | olculen bantta: evet | kilitlenen kalem  50
```

Ölçünün taşıyıcısı **tazeleme sayısıdır**; o sayı çalıştırmaya değil, kapsamın kalem sayısına
bağlıdır. Tek durumda bir kalemi değiştirmek altı yüz yirmi tazeleme gerektiriyor, bölünmüş
hâlde elli. Değişen kalem sayısı bire karşılık boşa giden okuma oranı yüzde doksan dokuzun
üzerinde. Beklenen plan süresi bu sayıdan türüyor — altı yüz yirmi milisaniyeye karşı elli — ve
ölçüm iki kapsamda da bandın içinde kaldı; süre doğrudan tazeleme sayısını izliyor.

**Etki yarıçapı** daha keskindir ve hiç zamana bağlı değildir: kilit altı yüz yirmi kalemin
tamamını kapsıyor. Gözlem katmanına eşik ekleyen kişi, plan boyunca üç ortamın tamamını — ağını,
veri deposunu, arşivini — kilitli tutuyor.

Bölünmüş hâlde aynı iş elli kalem tazeliyor ve elli kalem kilitliyor. Plan süresi on ikide bire,
etki yarıçapı yüzde yüzden yüzde sekize iniyor. Öteki on iki parçaya dokunan herkes aynı anda
çalışabilir; önceki dersteki bire inmiş eşzamanlılık tavanı on üçe çıkıyor.

Fark günlük çalışmada birikir. Ekip günde yirmi kez uygulama tetikliyorsa tek durumda toplam
plan süresi on iki saniyeye çıkar ve bu sürenin tamamı kilit altında geçer; bölünmüş hâlde aynı
yirmi uygulamanın çoğu farklı parçalara düştüğü için hem her biri kısalır hem de birbirini
beklemez. Ölçünün asıl anlamı süre değil, **bekleyen kişi sayısıdır**: tek durumda her uygulama
bütün ekibi bekletir, bölünmüş hâlde yalnız aynı parçaya dokunanları.

Bir başka etki plan çıktısının okunabilirliğidir. Altı yüz yirmi kalemin tazelendiği bir planda
değişen tek kalemi bulmak, elli kalemlik bir planda bulmaktan zordur; sapma da aynı yığının içinde
kaybolur. Kapsam küçüldükçe planın okunma olasılığı artar, okunan plan ise uygulanmadan önce
durdurulabilen tek şeydir.

## Bölmenin Bedeli

Bölme bağımlılıkları yok etmez, görünür kılar. Parça sınırını geçen altmış altı kenarın her biri
artık iki ayrı durum dosyası arasında kurulmak zorundadır.

```js
// bagimlilik.mjs — parcalar arasi kenarlari, cozum bicimlerini ve yeniden uygulama yayilimini sayar.
import { readFileSync, readdirSync } from "node:fs";

const parcalar = readdirSync("bolunmus").map((f) => f.replace(".json", ""));
const durum = {}, kalemParca = new Map();
for (const p of parcalar) {
  durum[p] = JSON.parse(readFileSync(`bolunmus/${p}.json`, "utf8")).kalemler;
  for (const k of durum[p]) kalemParca.set(k.ad, p);
}
// Cikti veren parcalar: degerlerini adiyla yayinlayanlar. Otekiler ancak sorgulanabilir.
const ciktiVeren = new Set(parcalar.filter((p) => /(^ortak$|_ag$|_veri$)/.test(p)));

const kenar = [];
for (const p of parcalar)
  for (const k of durum[p])
    for (const b of k.bagimli) { const h = kalemParca.get(b); if (h !== p) kenar.push([p, h]); }
const ciktiIle = kenar.filter(([, h]) => ciktiVeren.has(h)).length;

console.log(`parcalar arasi bagimlilik: ${kenar.length} kenar, ` +
  `${new Set(kenar.map((e) => e.join(">"))).size} ayri parca cifti`);
console.log(`  cikti okumayla cozulen: ${ciktiIle}, ` +
  `veri kaynagiyla cozulen: ${kenar.length - ciktiIle}`);
const gelen = {};
for (const [, h] of kenar) gelen[h] = (gelen[h] ?? 0) + 1;
console.log(`  en cok baglanilan: ` + Object.entries(gelen).sort((a, b) => b[1] - a[1])
  .slice(0, 3).map(([p, n]) => `${p} ${n} kenar`).join(", "));

// Veri kaynagi, sorguya uyan her seyi dondurur: kaydin kapsamadigi kaynagi da.
const saglayici = JSON.parse(readFileSync("saglayici.json", "utf8"));
const donen = saglayici.filter((a) => a.startsWith("uretim_hesaplama/")).length;
const kayitli = durum["uretim_hesaplama"].length;
console.log(`  veri kaynagi sorgusu (uretim_hesaplama): ${donen} kalem dondu, ` +
  `kayitta olan ${kayitli}, kayit disi ${donen - kayitli}`);
console.log(`  ayni bag cikti okumayla kurulsaydi: ${kayitli} kalem, kayit disi 0`);

const bagliOlan = {};                            // hedef parca -> ona bagli parcalar
for (const [k, h] of kenar) (bagliOlan[h] ??= new Set()).add(k);
const yayilim = (p) => {
  const gorulen = new Set([p]), yigin = [p];
  while (yigin.length) {
    const x = yigin.pop();
    for (const y of bagliOlan[x] ?? []) if (!gorulen.has(y)) { gorulen.add(y); yigin.push(y); }
  }
  return gorulen;
};
for (const p of ["uretim_gozlem", "uretim_veri", "uretim_ag", "ortak"]) {
  const g = yayilim(p);
  const kalem = [...g].reduce((t, x) => t + durum[x].length, 0);
  console.log(`  ${p.padEnd(13)} degisirse: ${String(g.size).padStart(2)} parca yeniden uygulanir, ` +
    `${String(kalem).padStart(3)} kalem tazelenir, ${String(g.size).padStart(2)} kilit alinir`);
}
```

**DM15.** Ağ ve veri katmanları ile bölge omurgası değerlerini adıyla **çıktı** olarak yayınlar;
hesaplama katmanı yayınlamaz, ona bağlanmak için **veri kaynağı** sorgusu gerekir. **DM16.**
Üretim hesaplama katmanında kaydın kapsamadığı üç kaynak duruyor.

```
parcalar arasi bagimlilik: 66 kenar, 18 ayri parca cifti
  cikti okumayla cozulen: 51, veri kaynagiyla cozulen: 15
  en cok baglanilan: deneme_ag 9 kenar, hazirlik_ag 9 kenar, uretim_ag 9 kenar
  veri kaynagi sorgusu (uretim_hesaplama): 53 kalem dondu, kayitta olan 50, kayit disi 3
  ayni bag cikti okumayla kurulsaydi: 50 kalem, kayit disi 0
  uretim_gozlem degisirse:  1 parca yeniden uygulanir,  50 kalem tazelenir,  1 kilit alinir
  uretim_veri   degisirse:  3 parca yeniden uygulanir, 150 kalem tazelenir,  3 kilit alinir
  uretim_ag     degisirse:  4 parca yeniden uygulanir, 200 kalem tazelenir,  4 kilit alinir
  ortak         degisirse: 13 parca yeniden uygulanir, 620 kalem tazelenir, 13 kilit alinir
```

Altmış altı kenar on sekiz parça çiftine dağılıyor. Elli biri **çıktı okumayla** çözülüyor: hedef
parça değeri adıyla yayınlıyor, bağlanan parça o adı okuyor. Bağ kayıtlıdır ve iki tarafı da
bilinir; bedeli bir sürüm bağıdır — hedef parça bir çıktıyı kaldırırsa ona bağlı kenarlar aynı
anda kırılır ve kırıldığı ancak uygulama anında öğrenilir.

Kenarların dağılımı da bir şey söylüyor: en çok bağlanılan üç parça, üç ortamın ağ katmanları ve
her biri dokuz kenar taşıyor. Bu üç parça bölmenin kırılma noktasıdır. Ağ katmanının çıktı
listesinde yapılan bir adlandırma değişikliği tek bir parçada yazılır, dokuz kenarda hissedilir
ve üç parçayı yeniden uygulatır. Çıktı adları bu yüzden parçaların **arayüzüdür**; parça içindeki
kaynak adları serbestçe değişebilir, çıktı adları değişemez.

Kalan on beşi **veri kaynağıyla** çözülüyor: hedef parça bağlanandan haberdar değil, bağlanan
taraf sağlayıcıya sorgu atıyor. Ölçüm bu yolun bedelini gösteriyor: sorgu elli üç kalem döndürdü,
kayıtta elli kalem var. Üç kalem kaydın kapsamadığı kaynaktır ve veri kaynağı onları da içeri
alır. Aynı bağ çıktı okumayla kurulsaydı dönen kalem sayısı elli, kayıt dışı sıfır olurdu.
Sorgu **gerçeği** okur, çıktı **kaydı** okur; ikisi bu üç kalem kadar ayrışır.

## Yeniden Uygulama Yayılımı

Son dört satır bölmenin asıl faturasıdır. **DM17.** Bir parçanın çıktısı değişince ona bağlı
parçalar yeniden uygulanır ve bu geçişlidir; bağlananın bağlananı da sıraya girer. Gözlem
parçasını değiştirmek bir parçayı yeniden uygulatıyor; ağ parçasını değiştirmek dördünü; bölge
omurgasını değiştirmek on üçünün tamamını.

Son satır dikkatle okunmalı: ortak parça değişince altı yüz yirmi kalem tazeleniyor — tek durum
dosyasındaki sayının aynısı — ama bu kez on üç ayrı kilit alınıyor ve on üç uygulama sıraya
konuyor. Bölme, geniş değişikliği ucuzlatmaz; **pahalılaştırır**. Tek durumda tek bir uygulama
her şeyi doğru sırada yaparken, bölünmüş hâlde sırayı kuran şey artık bir kişidir.

Kural buradan çıkar: bölme yeri, **değişim sıklığına** göre seçilir. Sık değişen katman kendi
parçasında durmalı ki etki yarıçapı küçük kalsın; seyrek değişen ve herkesin bağlandığı katman
tek bir parçada toplanmalı ki yayılımı sık tetiklenmesin. Yanlış yerden bölünürse iki zarar
birleşir: hem parçalar arası kenar sayısı büyür, hem her değişiklik çok parçaya yayılır.

## Kaydın Çoğalması

Bölme kaydı da çoğaltır ve bu kaydın kendi riskidir. Tek dosya on üç dosya oldu: on üç kilit, on
üç erişim noktası, on üç ayrı kayıp senaryosu. Önceki dersin ölçümü her biri için ayrı ayrı
geçerlidir. Bir parçanın durumunun kaybı yalnız o parçayı yönetilemez kılar — bu bir kazançtır —
ama kaybın fark edilmesi zorlaşır, çünkü öteki on iki parça sorunsuz uygulanmaya devam eder.

İkinci risk sınırın kendisindedir. Parça sınırı hiçbir durum dosyasında yazılı değildir; hangi
kalemin hangi parçaya ait olduğu yalnız dosyaların dağılımında görünür. Bir kalem yanlışlıkla iki
parçanın tanımına birden girerse iki kayıt aynı kaynağı sahiplenir ve iki uygulama sırayla
birbirinin işini bozar. Kilit bunu engellemez: iki farklı dosyanın kilidi farklıdır.

Üçüncü risk sınırı **değiştirmekte**dir. Bölme bir kez yapılıp bitmez; bir kalem zamanla yanlış
parçada kaldığı anlaşılır ve taşınması gerekir. Taşıma, tanımı bir dosyadan ötekine kopyalamak
değildir. Kalem eski parçanın tanımından çıkarıldığı anda o parçanın planı onu **silinecek**
olarak gösterir; yeni parçanın planı ise **oluşturulacak** olarak. İki plan da tek başına
doğrudur, ikisi arka arkaya uygulanırsa kaynak gerçekten silinir ve yeniden yaratılır. Doğru yol,
kalemin kaydını eski durumdan kimliğiyle çıkarıp yeni duruma kimliğiyle eklemektir — yani ilk
dersteki içe aktarmanın tersi ve devamı. Bu işlem iki dosyaya birden dokunduğu için iki kilidi
aynı anda gerektirir ve arada kalırsa kalem hiçbir kayıtta görünmez: kaydın kapsamadığı kaynak
sayısı üçten dörde çıkar.

## Özet

- Altı yüz yirmi kalemlik ağın altı yüz yetmiş üç kenarından yalnız altmış altısı parça sınırını
  geçiyor; bağların yüzde doksanı zaten yerel.
- Tek durumda bir kalemlik değişiklik altı yüz yirmi kalem tazeledi ve altı yüz yirmi kalemi
  kilitledi; bölünmüş hâlde aynı iş elli kalem tazeledi, elli kalem kilitledi.
- Parçalar arası altmış altı kenarın elli biri çıktı okumayla, on beşi veri kaynağıyla çözülüyor;
  veri kaynağı sorgusu elli üç kalem döndürdü, üçü kaydın dışındaydı.
- Bir parça değişince yeniden uygulanan parça sayısı bir ile on üç arasında değişiyor; bölge
  omurgası değişince on üç kilit ve altı yüz yirmi tazeleme gerekiyor.
- Bölme kilidi küçültür, koordinasyonu büyütür; bölme yeri değişim sıklığına göre seçilir.
- On üç dosya on üç kayıp senaryosu demektir ve parça sınırı hiçbir durum dosyasında yazılı
  değildir.

## Sonraki Adım

Bu dersin bölmesi katmana göre yapıldı: ağ, veri, hesaplama, gözlem. Parça adlarında ortam da
vardı ama ortam ayrımının nasıl kurulduğuna hiç bakılmadı. Üç ortamın tanımı aynıysa aynı metni
üç kez yazmak mı gerekir, yoksa tek tanımın üç örneği mi tutulur? İki kurulumun da bir bedeli
vardır ve bedel aynı yerde toplanır: uygulamayı başlatan kişinin hangi ortamda olduğunu bilmesi.
Sonraki ders üç ortamı iki ayrı biçimde kurar, yanlış ortama uygulama riskini adım sayısıyla
ölçer, ortama özgü farkları sayar ve tanım değiştiğinde kaç ortamın zorunlu olarak birlikte
değiştiğini karşılaştırır.
