---
title: 'Uzlaşma Döngüsü'
source: 'https://academia.sh/tr/kurslar/orkestrasyon/uzlasma-dongusu'
course: 'Konteyner Orkestrasyonu'
language: tr
updated: '2026-08-17T18:09:08+00:00'
license: 'CC BY-SA 4.0'
---

# Uzlaşma Döngüsü

İstenen durum ile gerçek durumun sürekli karşılaştırılması küme ölçeğinde çalışan bir döngüyle yazılır ve rapor gecikmesi taranır: sistem kaç gereksiz kopya açıyor, kaç kopyayı boşuna siliyor, salınımın genliği ne. Döngü periyodu ile rapor gecikmesi arasındaki bağıntı elli altı hücrede sınanır ve eksik bilgi kaleminin sistemin kendi geçmişi olduğu gösterilir.

Bu konunun ilk üç dersi iki tarafı ayrı ayrı ölçtü. Şimdi ikisini birbirine bağlayan şey yazılır:
istenen durum ile gerçek durumun sürekli karşılaştırılıp farkın kapatılması, yani **uzlaşma
döngüsü**. Döngünün kendisi yeni değildir — daha önce tek makinede çalışan bir uzlaştırıcı
görülmüştü: istenen durumu dosyadan, gerçek durumu diskten okuyor, yalnız farklı kaleme dokunuyor
ve ikinci koşumda sıfır iş yapıyordu. O ölçüm burada girdi olarak alınır ve tekrarlanmaz.

Küme ölçeğinde tek bir şey değişir. Gerçek durum artık diskten okunmaz; düğümlerden gelen ve bir
önceki dersin ölçtüğü gecikmeyi taşıyan **raporlardan** gelir. Bu dersin tamamı o tek farkın
bedelini sayar: gecikmeli bir görüntüye bakarak verilen doğru kararlar, kaç yanlış düzeltme
üretiyor.

Ölçüm yine **bölgesel ölçüm ağı** üzerindedir ve **kurgudur**; koşan şey `node` ile kurulmuş bir
**modeldir**, gerçek bir küme değil.

**KM19.** İstenen durum tek kalemdir: toplayıcı servisinin kopya sayısı altıdır ve insanın yazdığı
bildirimden gelir.
**KM20.** Gerçek durum düğüm raporlarından gelir; defter gerçek dünyanın G saniye gerisindedir.
**KM21.** Yaratılan bir kopya B saniye sonra çalışır hâle gelir, çalıştığı bilgisi G saniye sonra
deftere düşer; silinen bir kopya da defterden G saniye sonra kaybolur.
**KM22.** Döngü periyodu U'dur; her turda defter okunur, fark hesaplanır, düzeltme yazılır.
**KM23.** Olaylar yazılıdır, rastgelelik yoktur: 300. saniyede iki kopya ölür; koşum 900 saniyedir.
**KM24.** İki denetleyici karşılaştırılır — yalnız deftere bakan, ve kendi bekleyen eylemlerini de
sayan.
**KM25.** Silme komutu defterde görünene verilir; zaten ölmüş bir kopyaya verilen komut iş olarak
sayılır ama canlı kopya sayısını değiştirmez.

## Küme Ölçeğinde Uzlaşma Döngüsü

```js
// uzlas.mjs — kume olceginde uzlasma dongusu. Istenen durum bildirimden, gercek durum
// gecikmeli raporlardan gelir. Model; gercek kume kosturulmaz. Rastgelelik yok, olaylar yazili.
export const OLUM = [[300, 2]];              // yazili olay: 300. saniyede 2 kopya olur

export function kos({ istenen = 6, U = 15, G = 0, B = 5, sure = 900, niyet = false }) {
  const gercek = [];                          // {dogum, hazir, olum}
  let yaratildi = 0, komut = 0, silindi = 0, is = 0, tur = 0, asim = 0, sonSapma = 0;
  const canli = (t) => gercek.filter((r) => r.hazir <= t && (r.olum === null || r.olum > t));
  const gorunen = (t) => gercek.filter((r) =>            // defter G saniye geride
    r.hazir + G <= t && (r.olum === null || r.olum + G > t));

  for (let t = 0; t <= sure; t++) {
    for (const [an, kac] of OLUM)                        // yazili olum: en eski kopyalar duser
      if (t === an) canli(t).slice(0, kac).forEach((r) => { r.olum = t; });
    if (t % U === 0) {
      tur++;
      const g = gorunen(t);
      const bekleyen = niyet ? gercek.filter((r) => r.olum === null && r.hazir + G > t).length : 0;
      const fark = istenen - g.length - bekleyen;        // niyet: kendi bekleyen eylemlerini say
      if (fark > 0) {
        for (let i = 0; i < fark; i++) gercek.push({ dogum: t, hazir: t + B, olum: null });
        yaratildi += fark; is += fark;
      } else if (fark < 0) {
        komut += -fark; is += -fark;                     // silme komutu: defterde gorunene verilir
        g.slice(0, -fark).forEach((r) => { if (r.olum === null) { r.olum = t; silindi++; } });
      }
    }
    const c = canli(t).length;
    asim = Math.max(asim, c - istenen);
    if (c !== istenen) sonSapma = t;
  }
  const gerekli = istenen + OLUM.reduce((s, k) => s + k[1], 0);
  return { tur, isTur: is / tur, yaratildi, gereksiz: yaratildi - gerekli, komut, silindi, asim,
    kararli: sonSapma === sure ? null : sonSapma + 1 };
}

const satir = (ilk, r) => `${ilk}${r.isTur.toFixed(2).padStart(8)}${String(r.yaratildi).padStart(11)}` +
  `${String(r.gereksiz).padStart(10)}${String(r.komut).padStart(14)}${String(r.silindi).padStart(9)}` +
  `${String(r.asim).padStart(6)}${(r.kararli === null ? "yok" : r.kararli).toString().padStart(13)}`;

if (import.meta.url === `file://${process.argv[1]}`) {
  console.log("U=15 sn dongu, B=5 sn baslama, istenen 6 kopya, 300. sn'de 2 olum, 900 sn kosum");
  for (const niyet of [false, true]) {
    console.log(`\ndenetleyici: ${niyet ? "defter + kendi bekleyen eylemleri" : "yalniz defter"}`);
    console.log("G(sn)  is/tur  yaratilan  gereksiz  silme komutu  silinen  asim  kararli(sn)");
    for (const G of [0, 5, 10, 20, 30, 60])
      console.log(satir(String(G).padStart(5), kos({ G, niyet })));
  }
}
```

```
U=15 sn dongu, B=5 sn baslama, istenen 6 kopya, 300. sn'de 2 olum, 900 sn kosum

denetleyici: yalniz defter
G(sn)  is/tur  yaratilan  gereksiz  silme komutu  silinen  asim  kararli(sn)
    0    0.13          8         0             0        0     0          305
    5    0.13          8         0             0        0     0          320
   10    0.13          8         0             0        0     0          320
   20    0.52         16         8            16        8     6          375
   30    0.92         24        16            32       16    12          405
   60    2.75         40        32           128       32    24          495

denetleyici: defter + kendi bekleyen eylemleri
G(sn)  is/tur  yaratilan  gereksiz  silme komutu  silinen  asim  kararli(sn)
    0    0.13          8         0             0        0     0          305
    5    0.13          8         0             0        0     0          320
   10    0.13          8         0             0        0     0          320
   20    0.13          8         0             0        0     0          335
   30    0.13          8         0             0        0     0          335
   60    0.13          8         0             0        0     0          365
```

Üst tablonun ilk üç satırı tanıdıktır. Gecikme sıfır, beş ya da on saniyeyken döngü sekiz kopya
yarattı — altısı ilk kurulum, ikisi ölenlerin yerine — hiçbirini boşuna silmedi, hiç aşım yapmadı.
Tur başına iş 0,13'tür: kırk bir turun otuz sekizi sıfır iş yaptı. Tek makinede ölçülen etkisizlik
küme ölçeğinde de duruyor.

Dördüncü satırda döngü davranış değiştirir. Yirmi saniyelik rapor gecikmesinde döngü on altı kopya
yarattı; sekizi gereksizdi. Sekiz kopya boşuna silindi ve canlı kopya sayısı altı yerine on ikiye
çıktı. Altmış saniyelik gecikmede tablo iyice bozulur: kırk kopya yaratıldı, otuz ikisi gereksiz;
yüz yirmi sekiz silme komutu verildi; aşım yirmi dört, yani bir ara **otuz kopya** çalıştı.

Bu satırlarda dikkat edilecek yer denetleyicinin hiçbir hata yapmamış olmasıdır. Her turda defteri
okudu, farkı doğru hesapladı ve tam da o farkı kapatacak düzeltmeyi yazdı. Kural doğru, aritmetik
doğru, girdi eski. Kopyalar yaratıldı ama henüz raporlanmadıkları için denetleyici bir sonraki
turda onları göremedi ve **aynı eksiği yeniden gördü**. Yanlış düzeltmenin kaynağı karar kuralı
değil, kararın dayandığı görüntünün yaşıdır.

Silme komutu ile gerçekten silinen kopya arasındaki fark aynı körlüğün ikinci yüzüdür. Altmış
saniyelik gecikmede 128 silme komutu verildi, bunların yalnız 32'si canlı bir kopyaya denk geldi;
kalan 96 komut zaten ölmüş kopyalara gitti. Sistem yalnız kendi yarattığını değil, **kendi
sildiğini de** gecikmeyle görür.

Ölçüm ağında bunun karşılığı somuttur: altı kopyalık toplayıcı servisi bir ara otuz kopyayla
çalıştı, arkasındaki veritabanına beş kat bağlantı açıldı ve aynı sayaç okuma partileri birden çok
kopya tarafından çekildi. Salınım bir gösterge sorunu değil, gerçek bir yük. Üstelik bu yükün hiçbir kaydı, denetleyicinin "altı kopya istendi, altı kopya var" diyen son satırında görünmez; salınım kapandıktan sonra geriye yalnız doğru bir son durum kalır.

## Döngü Periyodu ile Rapor Gecikmesinin İlişkisi

```js
// oran.mjs — dongu periyodu U ile rapor gecikmesi G arasindaki iliski sayiyla.
import { kos } from "./uzlas.mjs";
const B = 5, ISTENEN = 6;
const ongoru = (G, U) => ISTENEN * (Math.ceil((G + B) / U) - 1);   // sinanacak baginti

console.log("G=30 sn sabit, B=5 sn; dongu periyodu taraniyor");
console.log("U(sn)  ceil((G+B)/U)  ongorulen asim  olculen asim  gereksiz  silinen  is/tur");
for (const U of [5, 10, 15, 20, 30, 35, 60]) {
  const r = kos({ U, G: 30, B });
  console.log(`${String(U).padStart(5)}${String(Math.ceil(35 / U)).padStart(15)}` +
    `${String(ongoru(30, U)).padStart(16)}${String(r.asim).padStart(14)}` +
    `${String(r.gereksiz).padStart(10)}${String(r.silindi).padStart(9)}` +
    `${r.isTur.toFixed(2).padStart(8)}`);
}

console.log("\nasim tablosu (satir: rapor gecikmesi G, sutun: dongu periyodu U)");
const U_LER = [5, 10, 15, 20, 30, 45, 60, 90];
console.log("G\\U  " + U_LER.map((u) => String(u).padStart(5)).join(""));
let sapma = 0, hucre = 0;
for (const G of [0, 10, 20, 30, 45, 60, 90]) {
  const s = U_LER.map((U) => { const a = kos({ U, G, B }).asim; hucre++;
    if (a !== ongoru(G, U)) sapma++; return String(a).padStart(5); });
  console.log(String(G).padStart(3) + "  " + s.join(""));
}
console.log(`\nbaginti asim = istenen x (ceil((G+B)/U) - 1);  ${hucre} hucrenin ${sapma} tanesi sapiyor`);
```

```
G=30 sn sabit, B=5 sn; dongu periyodu taraniyor
U(sn)  ceil((G+B)/U)  ongorulen asim  olculen asim  gereksiz  silinen  is/tur
    5              7              36            36        48       48    1.90
   10              4              18            18        24       24    1.14
   15              3              12            12        16       16    0.92
   20              2               6             6         8        8    0.70
   30              2               6             6         8        8    0.77
   35              1               0             0         0        0    0.31
   60              1               0             0         0        0    0.50

asim tablosu (satir: rapor gecikmesi G, sutun: dongu periyodu U)
G\U      5   10   15   20   30   45   60   90
  0      0    0    0    0    0    0    0    0
 10     12    6    0    0    0    0    0    0
 20     24   12    6    6    0    0    0    0
 30     36   18   12    6    6    0    0    0
 45     54   24   18   12    6    6    0    0
 60     72   36   24   18   12    6    6    0
 90    108   54   36   24   18   12    6    6

baginti asim = istenen x (ceil((G+B)/U) - 1);  56 hucrenin 0 tanesi sapiyor
```

Üst tablo tek bir gecikmeyi (30 saniye) sabit tutup döngü periyodunu tarıyor ve beklenmedik yönü
gösteriyor: **döngüyü hızlandırmak zararı büyütür.** Beş saniyelik periyotta aşım otuz altı,
gereksiz kopya kırk sekizdir; otuz beş saniyelik periyotta ikisi de sıfırdır. Sık uzlaşan bir
döngü, gecikme sabitken aynı eski görüntüyü daha çok kez okur ve her okumada aynı eksiği yeniden
kapatmaya çalışır.

Alt tablo bağıntıyı verir. Aşım, ölçülen bütün hücrelerde şu değerdedir:

**aşım = istenen kopya × (⌈(G + B) / U⌉ − 1)**

Elli altı hücrenin hiçbirinde sapma yok. Bağıntının okunuşu basittir: `(G + B) / U`, bir kopyanın
yaratılmasından defterde görünmesine kadar geçen sürede **kaç tur** koştuğudur. O turların ilki
gerçek eksiği kapatır; kalanların her biri aynı eksiği bir kez daha kapatır. Kör tur sayısı bir
olduğunda — yani `U ≥ G + B` — aşım sıfırlanır ve tablonun sıfır bölgesi tam olarak bu köşegenin
üstünde kalır.

Bu, bir önceki dersin canlılık eşiği kuralının kardeşidir. Orada eşiğin en uzun geçici kesintiyi
artı bir bildirim periyodunu geçmesi gerekiyordu; burada döngü periyodunun rapor gecikmesini artı
başlama süresini geçmesi gerekiyor. İkisinde de kümenin ayarı, kümenin kendi ölçmediği bir süreye
bağlıdır ve ikisinde de yanlış ayarın alarmı yoktur — salınım sessizce çalışır. Bağıntının
kendisi de bu yüzden işletim değeri taşır: aşımı görmeden, yalnız üç süreyi bilerek hesaplamak
mümkündür.

G burada serbest bir ayar değildir; bir önceki ders onu ölçmüştü. Dört aşamalı bildirim
zincirinin ortalaması 13,53, en kötüsü 26,36 saniyeydi. Beş saniyelik başlama süresiyle birlikte
`G + B` ortalamada 18,5, en kötü durumda 31,4 saniye eder. On beş saniyelik bir döngü periyodu bu
sayıların ikisinin de altındadır — yani ölçülen gecikmelerle çalışan bir küme, hiçbir şey
bozulmadan, **varsayılan ayarında salınım bölgesindedir**. Tablodaki `U=15, G=20` satırı bir uç
durum değil, sıradan bir gündür.

Döngünün taban maliyeti de burada görünür. Tur başına iş 0,13'tür ve turların çoğu sıfır iş yapar,
ama sıfır iş yapan tur bedava değildir: her tur defteri baştan okur. Bir önceki dersin doğrulama
turu bu okumayı 26 kalem olarak saymıştı. Döngünün maliyeti yaptığı düzeltmelerle değil, **kalem
sayısı ile periyodun oranıyla** büyür; periyodu küçültmek hem okuma yükünü hem — gecikme sabitse —
aşımı büyütür.

## Eksik Olan Kalem Sistemin Kendi Geçmişidir

Alt tablo ikinci denetleyiciyi gösteriyor ve sonuç keskindir: kendi bekleyen eylemlerini sayan
denetleyici bütün gecikme değerlerinde sekiz kopya yarattı, sıfır gereksiz, sıfır silme, tur başına
0,13 iş. Aşım her satırda sıfırdır.

Eklenen bilgi kalemi tek bir satırdır ve dünyayla ilgili değildir: **son turlarda ne yarattığımın
kaydı.** Denetleyici artık "defterde altı yerine dört kopya görüyorum" demiyor; "defterde dört
kopya görüyorum ve iki tanesini iki tur önce ben yarattım, henüz görünmemiş olabilirler" diyor.
Kursun ölçüsü buraya oturur: devredilen karar doğru verilebilsin diye eklenen kalem, çoğu zaman
bir ölçüm değil, sistemin **kendi eylemlerinin hafızasıdır** — ve bu kalem bedavaya yakındır,
çünkü kimseden bildirim istemez.

Bedavaya yakındır ama her şeyi çözmez. İki tablonun son sütunu karşılaştırıldığında görülür:
niyet kaydı olan denetleyicide de kararlı hâle gelme anı gecikmeyle birlikte büyüyor — 305
saniyeden 365 saniyeye. Ölen iki kopyanın yerine yenisi, ölüm defterde görünene kadar açılamaz.
Ayrım tek cümleye iner: **gecikme fark etmeyi geciktirir, kayıtsız niyet ise işi çoğaltır.** Bunlar
ayrı iki sorundur; ikincisi bir satırla kapanır, birincisi kapanmaz — yalnız bildirim periyodu ve
ağ gecikmesi küçültülerek pahalıya azaltılır — ve bir önceki dersin gösterdiği gibi, o periyotları küçültmenin faturası düğüm başına bildirim yükü olarak geri gelir.

## Özet

- Rapor gecikmesi sıfır, 5 ve 10 saniyeyken döngü 8 kopya yarattı, hiç boşuna silme yapmadı ve 41
  turun 38'i sıfır iş yaptı; tek makinede ölçülen etkisizlik küme ölçeğinde de duruyor.
- 20 saniyelik gecikmede 8 gereksiz kopya açıldı, 8 kopya boşuna silindi, canlı sayı 6 yerine 12'ye
  çıktı; 60 saniyede 32 gereksiz kopya, 128 silme komutu ve 30 canlı kopyalık bir salınım oluştu.
- 128 silme komutunun yalnız 32'si canlı bir kopyaya denk geldi; sistem kendi yarattığını da, kendi
  sildiğini de gecikmeyle görüyor.
- Aşım bütün taramalarda `istenen × (⌈(G+B)/U⌉ − 1)` çıktı; 56 hücrede sıfır sapma. Aşımın
  sıfırlandığı sınır `U ≥ G + B`, yani döngü periyodunun rapor gecikmesi artı başlama süresini
  geçmesidir.
- Döngüyü hızlandırmak zararı büyüttü: 30 saniyelik gecikmede periyot 5 saniyeyken aşım 36, periyot
  35 saniyeyken 0.
- Kendi bekleyen eylemlerini sayan denetleyici bütün gecikmelerde 0 gereksiz kopya ve 0 boşuna
  silme yaptı; kararlı olma anı yine de 305'ten 365 saniyeye çıktı — gecikme fark etmeyi geciktirir,
  kayıtsız niyet işi çoğaltır.

## Sonraki Adım

Bu ders döngünün kendisini ölçtü: neyi okuduğunu, ne sıklıkta koştuğunu, gecikmeli bir görüntüyle
ne kadar yanlış iş yaptığını. Konunun son dersi bir işletim kararına döner — bu düzlemi kendin mi
işleteceksin, yoksa işletimini başkasına mı devredeceksin. Ölçülecek şey iki seçeneğin aynı
kalemlerde karşılaştırılmasıdır: devredilen işletim kalemi sayısı, elde kalan kalem, sürüm
yükseltme penceresi, denetim düzlemine erişimin kaybı ve kararın geri alınabilirliği.
