---
title: 'Eşzamansız İşlemenin Gerekçesi'
source: 'https://academia.sh/tr/kurslar/eszamansiz-isleme/eszamansiz-islemenin-gerekcesi'
course: 'Önbellekleme, Kuyruklar ve Eşzamansız İşleme'
language: tr
updated: '2026-08-17T18:06:47+00:00'
license: 'CC BY-SA 4.0'
---

# Eşzamansız İşlemenin Gerekçesi

İstek yolunun işi çıkararak kısaltılması: adım maliyetlerinin ve başarı olasılığının ölçülmesi, isteğin içinde kalması zorunlu iş ile ertelenebilir işin ayrılması, yanıtın anlamının değişmesi ve devrin bellekte yapılmasıyla giden kutusuna yazılması arasındaki dayanıklılık farkı.

Önceki ders önbellek isabet oranını ölçtü ve okuma yolunun ne kadar kısaldığını sayıyla
gösterdi. Aynı ders bir sınırı da işaretledi: önbellek yalnız okumaya yarar. Ödünç verme
isteği bir yazmadır, üstelik yazmanın yanında sürüklediği başka işler vardır — üyeye
gecikme bildirimi, şube stok özetinin yeniden hesaplanması, aylık rapora bir satır. Bunların
hiçbiri önbelleklenemez ve hepsi isteğin süresine eklenir.

İstek yolunu kısaltmanın ikinci yolu işi hızlandırmak değil, işi istekten **çıkarmaktır**.
Bu ders üç soruyu sırayla yanıtlar: isteğin içinde ne kalmak zorundadır, ne çıkarılabilir,
çıkarmanın bedeli nedir.

## İsteğin İçindeki İş

Ödünç verme isteğinin beş adımı var. Her adımın maliyeti aşağıdaki modelde bildirilmiştir;
bu değerler ölçülmüş süreler değil, adımların birbirine göre büyüklüğünü temsil eden model
değerleridir. Asıl ilgilendiğimiz, hangi adımın toplam süreye ne kattığıdır.

```js
// istek-yolu.mjs — odunc verme isteginin adimlari ve her adimin modellenmis maliyeti
const ADIMLAR = [
  { ad: "yetki denetimi",           ms: 3,   yaniti_belirler: true  },
  { ad: "odunc kaydinin yazilmasi", ms: 9,   yaniti_belirler: true  },
  { ad: "gecikme bildirimi",        ms: 140, yaniti_belirler: false },
  { ad: "sube stok ozetinin yeniden hesabi", ms: 260, yaniti_belirler: false },
  { ad: "aylik rapor satiri",       ms: 55,  yaniti_belirler: false },
];

let birikim = 0;
for (const a of ADIMLAR) {
  birikim += a.ms;
  const isaret = a.yaniti_belirler ? "zorunlu " : "ertelenebilir";
  console.log(`${a.ad.padEnd(40)} ${String(a.ms).padStart(4)} ms  ${isaret}  birikim=${birikim} ms`);
}

const toplam = ADIMLAR.reduce((t, a) => t + a.ms, 0);
const zorunlu = ADIMLAR.filter((a) => a.yaniti_belirler).reduce((t, a) => t + a.ms, 0);
console.log(`\nistek suresi (hepsi istekte)      = ${toplam} ms`);
console.log(`istek suresi (yalniz zorunlu is)  = ${zorunlu} ms`);
console.log(`kisalma orani                     = ${(1 - zorunlu / toplam).toFixed(3)}`);

// Tek is parcasi saniyede kac istek bitirebilir?
console.log(`tek is parcasinin verimi: ${(1000 / toplam).toFixed(1)} -> ${(1000 / zorunlu).toFixed(1)} istek/s`);

// Her adim bir dis bagimliliktir; istegin basarisi hepsinin ayni anda calismasina baglidir.
const p = 0.999;
const hepsi = p ** ADIMLAR.length, azi = p ** ADIMLAR.filter((a) => a.yaniti_belirler).length;
console.log(`istek basari olasiligi: ${hepsi.toFixed(5)} -> ${azi.toFixed(5)}`);
```

```sh
node istek-yolu.mjs
```

```
yetki denetimi                              3 ms  zorunlu   birikim=3 ms
odunc kaydinin yazilmasi                    9 ms  zorunlu   birikim=12 ms
gecikme bildirimi                         140 ms  ertelenebilir  birikim=152 ms
sube stok ozetinin yeniden hesabi         260 ms  ertelenebilir  birikim=412 ms
aylik rapor satiri                         55 ms  ertelenebilir  birikim=467 ms

istek suresi (hepsi istekte)      = 467 ms
istek suresi (yalniz zorunlu is)  = 12 ms
kisalma orani                     = 0.974
tek is parcasinin verimi: 2.1 -> 83.3 istek/s
istek basari olasiligi: 0.99501 -> 0.99800
```

Üç sayı okunmaya değer. Birincisi süre: isteğin işini yapan iki adım 12 milisaniye tutuyor,
geri kalan 455 milisaniye üyenin yanıtı beklediği ölü zaman. İkincisi verim: aynı iş
parçası bu ölü zamanı taşımadığında birim zamanda kırk kat fazla istek bitiriyor. Üçüncüsü
başarı olasılığı: her adım ayrı bir dış bağımlılıktır ve isteğin başarılı olması hepsinin
aynı anda çalışmasına bağlıdır. Beş bağımlılık iki bağımlılığa indiğinde başarısızlık oranı
binde beşten binde ikiye düşüyor. Rapor sunucusunun erişilemez olması artık ödünç vermeyi
engellemiyor.

## Zorunlu İş ile Ertelenebilir İş

Ayrımı yapan ölçüt hız değildir. Gecikme bildirimi hızlı olsaydı da isteğin içinde kalması
gerekmezdi; asıl soru şudur: **bu adım yapılmazsa yanıt yanlış olur mu?**

Üç durumda iş isteğin içinde kalır. Adım yanıtın içeriğini belirliyorsa — ödünç kimliği
yanıtta dönüyorsa kaydın yazılması ertelenemez. Adım isteğin reddine yol açabiliyorsa —
yetki denetimi ya da stok kısıtı sonradan çalıştırılamaz, çünkü üyeye "verildi" denmiş
olurdu. Adım bir değişmezi koruyorsa — kitabın aynı anda iki üyeye verilmemesi kuralı ödünç
kaydıyla aynı işlem sınırının içinde kalmak zorundadır; İşlem Sınırları dersinde kurulan
kural budur.

Kalan iş ertelenebilir. Ertelenebilir işin ortak özelliği, **sonunda** yapılmasının
yetmesidir: bildirim iki saniye sonra gitse de doğrudur, stok özeti bir dakika geriden
gelse de rapor doğruyu gösterir. İş Mantığı Yerleşimi konusunda alan olaylarının dinleyicisi
için konan ölçüt aynıdır: dinleyiciye verilen iş, yapılmasa da ödünç kaydının geçerli kaldığı
iştir.

## Devrin Bedeli: Yanıtın Anlamı Değişir

İş çıkarıldığında yanıt artık "yapıldı" demez, "kabul edildi" der. API Tasarımı kursunun
Eşzamanlı ve Eşzamansız API'ler dersinde kurulan kalıp burada karşılığını bulur: sunucu
`202` döndürür ve işin izleneceği kaynağı bildirir. Bu değişimin üç sonucu vardır.

İstemci işin bittiğini yanıttan öğrenemez; sormak ya da bildirilmek zorundadır. Hata artık
istemciye dönmez; ertelenmiş iş başarısız olduğunda ortada yanıtını bekleyen kimse yoktur,
dolayısıyla hatanın görülmesi ayrı bir düzenek ister. Ve iki uç arasında bir **mesaj** doğar:
bir tarafın yazdığı, başka bir tarafın sonra okuyacağı kayıt.

Mesajın nereye yazıldığı, bu dersin son ölçümünün konusudur.

## Devir Dayanıklı Olmalı

İşi istekten çıkarmanın en kısa yolu, onu aynı süreçte sonraya bırakmaktır: bir diziye koy,
yanıtı döndür, sonra işle. Ölçüm bunun neyi kaybettiğini gösterir. Aşağıdaki kurulum Veri Erişim Katmanı ve İş Mantığı
kursunda kullanılan tabloların aynısını kurar.

```sh
# kur.sh — kutuphane veritabanini sifirdan kurar
rm -f kutuphane.db
sqlite3 kutuphane.db <<'SQL'
CREATE TABLE sube (sube_id INTEGER PRIMARY KEY, ad TEXT NOT NULL);
CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, ad TEXT NOT NULL);
CREATE TABLE kitap (kitap_id INTEGER PRIMARY KEY, baslik TEXT NOT NULL, sube_id INTEGER NOT NULL);
CREATE TABLE odunc (odunc_id INTEGER PRIMARY KEY, kitap_id INTEGER NOT NULL,
                    uye_id INTEGER NOT NULL, alis_tarihi TEXT NOT NULL, iade_tarihi TEXT);
CREATE TABLE giden_kutusu (ileti_id INTEGER PRIMARY KEY, tur TEXT NOT NULL,
                           govde TEXT NOT NULL, durum TEXT NOT NULL DEFAULT 'bekliyor');
INSERT INTO sube VALUES (1,'Merkez'),(2,'Bahcelievler');
INSERT INTO uye VALUES (1,'Ayse Demir'),(2,'Bora Kaya'),(3,'Ceren Ak');
INSERT INTO kitap VALUES (1,'Korluk',1),(2,'Kum Kitabi',1),(3,'Puslu Kitalar',2);
SQL
```

İlk sürüm yan işleri bellekteki bir diziye bırakır. Sürecin dizi boşaltılmadan sonlanması
`process.exit` ile temsil edilmiştir; gerçek karşılığı dağıtımın yeni sürümü yerleştirmesi
ya da sürecin çökmesidir.

```js
// bellekte.mjs — yan isler bellekteki bir diziye birakilir; surec bosaltmadan sonlanir
import { DatabaseSync } from "node:sqlite";
const db = new DatabaseSync("kutuphane.db");
const yanIsler = [];

function oduncVer(uyeId, kitapId) {
  db.exec("BEGIN IMMEDIATE");
  const oduncId = Number(db.prepare(
    "INSERT INTO odunc (kitap_id, uye_id, alis_tarihi) VALUES (?,?,'2025-07-20')")
    .run(kitapId, uyeId).lastInsertRowid);
  db.exec("COMMIT");
  for (const tur of ["gecikme_bildirimi", "stok_ozeti", "rapor_satiri"])
    yanIsler.push({ tur, oduncId });
  return oduncId;
}

for (const [uyeId, kitapId] of [[1, 1], [2, 2], [3, 3]]) oduncVer(uyeId, kitapId);
console.log(`istek bitti; bellekte bekleyen yan is = ${yanIsler.length}`);
process.exit(0);   // surec yeniden baslatildi: dizi bosaldi
```

İkinci sürüm aynı yan işleri ödünç kaydıyla **aynı işlemde** giden kutusuna yazar. Giden
kutusu düzeni Alan Olayları dersinde tanıtılmıştı; buradaki kullanımı aynıdır, yalnız
yazılan şey bir alan olayı değil, yapılacak bir iştir.

```js
// giden-kutusuyla.mjs — yan isler odunc kaydiyla ayni islemde giden kutusuna yazilir
import { DatabaseSync } from "node:sqlite";
const db = new DatabaseSync("kutuphane.db");

function oduncVer(uyeId, kitapId) {
  db.exec("BEGIN IMMEDIATE");
  const oduncId = Number(db.prepare(
    "INSERT INTO odunc (kitap_id, uye_id, alis_tarihi) VALUES (?,?,'2025-07-20')")
    .run(kitapId, uyeId).lastInsertRowid);
  for (const tur of ["gecikme_bildirimi", "stok_ozeti", "rapor_satiri"])
    db.prepare("INSERT INTO giden_kutusu (tur, govde) VALUES (?,?)")
      .run(tur, JSON.stringify({ oduncId, uyeId, kitapId }));
  db.exec("COMMIT");
  return oduncId;
}

for (const [uyeId, kitapId] of [[1, 1], [2, 2], [3, 3]]) oduncVer(uyeId, kitapId);
console.log("istek bitti; yan isler giden kutusunda");
process.exit(0);   // surec yeniden baslatildi
```

Yeniden başlatılmış süreç geriye ne kaldığını sayar.

```js
// sayim.mjs — yeniden baslatilmis surec: geriye ne kaldi
import { DatabaseSync } from "node:sqlite";
const db = new DatabaseSync("kutuphane.db");
const say = (s) => db.prepare(s).get().n;
console.log(`odunc satiri = ${say("SELECT count(*) AS n FROM odunc")}, ` +
            `kurtarilabilir yan is = ${say("SELECT count(*) AS n FROM giden_kutusu WHERE durum = 'bekliyor'")}`);
```

```sh
sh kur.sh
node bellekte.mjs
node sayim.mjs
sh kur.sh
node giden-kutusuyla.mjs
node sayim.mjs
```

```
istek bitti; bellekte bekleyen yan is = 9
odunc satiri = 3, kurtarilabilir yan is = 0
istek bitti; yan isler giden kutusunda
odunc satiri = 3, kurtarilabilir yan is = 9
```

Her iki sürümde de üç ödünç kaydı yazıldı ve üç üye yanıtını hızlı aldı. Fark kurtarılabilir
yan iş sayısındadır: bellekte biriken dokuz iş süreçle birlikte yok oldu, giden kutusuna
yazılan dokuz iş yeniden başlatılan süreç tarafından bulundu. Üç üye bildirim almadı ve
kimse bunu fark etmedi — çünkü isteğe dönen yanıt zaten başarılıydı.

Buradan çıkan kural, eşzamansız işlemenin temel koşuludur: **iş istekten çıkarılıyorsa,
çıkarıldığı yerin kalıcı olması gerekir.** İşin devri, yapıldığı işlemle aynı atomikliği
paylaşmalıdır; yoksa kayıp sessiz olur.

## Ne Zaman Çıkarılmaz

Karşı yönde de bir maliyet vardır. Çıkarılan iş, isteği yapan için görünmez olur: üye
kitabı aldığını görür, bildirimin gelip gelmediğini bilmez. İşin durumu ayrı bir kaynakla
izlenmiyorsa hata kimsenin görmediği bir yerde birikir.

İkinci maliyet gecikmedir. Yan iş "sonunda" yapılır, ama o "sonunda" ölçülmüyorsa
sınırsızdır. Üç ölçüt işi isteğin içinde tutmayı haklı kılar: yanıtın içeriği o işe
bağlıysa, iş bir değişmezi koruyorsa, ya da işin gecikmesi kullanıcı için hatadan ayırt
edilemiyorsa.

Üçüncüsü karmaşıklıktır. Bellekte iki satırla yapılan devir, kalıcı hâle geldiğinde bir
tablo, bir okuyucu döngü, bir yeniden deneme kuralı ve bir hata yalıtımı gerektirir. Bu
dersten sonrası, o dört parçanın nasıl kurulduğudur.

## Özet

- İstek yolundaki beş adımdan ikisi yanıtı belirliyordu; kalan üçü çıkarıldığında modelde
  istek süresi 467 milisaniyeden 12 milisaniyeye, dış bağımlılık sayısı beşten ikiye indi.
- Aynı iş parçasının verimi 2,1 istek/s değerinden 83,3 istek/s değerine, istek başarı
  olasılığı 0,99501 değerinden 0,99800 değerine çıktı.
- Bir adım yanıtın içeriğini belirliyor, isteğin reddine yol açabiliyor ya da bir değişmezi
  koruyorsa isteğin içinde kalır; kalan iş ertelenebilir.
- İş çıkarıldığında yanıtın anlamı "yapıldı" olmaktan çıkıp "kabul edildi" olur; hata artık
  istemciye dönmediği için görünürlüğü ayrı kurulur.
- Yan işler bellekte biriktirildiğinde süreç sonlanınca dokuzu da kayboldu; aynı işlemde
  giden kutusuna yazıldığında dokuzu da yeniden başlatılan süreçte bulundu.

## Sonraki Adım

Giden kutusu işi kalıcı kıldı, ama tek başına bir taşıma düzeneği değil. Satırları kim
okuyacak, iki okuyucu aynı satırı aynı anda alırsa ne olacak, bir okuyucu satırı alıp
işlemeden çökerse o iş nasıl geri dönecek? Bunlar tek bir yapının soruları: iki uç arasında
mesaj taşıyan **kuyruk**. Sonraki ders kuyruğu en küçük hâliyle kurar — üretici, tüketici,
onay ve görünmezlik süresi — ve her mesajın kaç kez teslim edildiğini sayarak teslim
garantisinin ne anlama geldiğini ölçer.
