---
title: 'Nesne Depolama Servisi'
source: 'https://academia.sh/tr/kurslar/vaka-calismalari/nesne-depolama-servisi'
course: 'Vaka Çalışmaları'
language: tr
updated: '2026-08-17T18:10:55+00:00'
license: 'CC BY-SA 4.0'
---

# Nesne Depolama Servisi

Hacmin tasarımı belirlediği ilk vaka: parça boyunun kesinti olasılığına göre seçilmesi, fazladan gönderilen baytın süreç içi bir modelde ölçülüp kapalı biçimle doğrulanması, kopya sayısı ile silme kodlamasının saklama katı ve yıllık kayıp üzerinden karşılaştırılması ve küçük nesnede kodlamanın istek sayısıyla elenmesi.

Önceki konu beş vakayı yazma tarafından savundu ve hepsinde ortak bir nokta vardı: veri
**küçüktü** ve kayıt başına anlamlıydı. Tasarımı hacim değil, kaydın doğruluğu, sırası ve teslim
garantisi belirledi.

Bu konu o varsayımı kaldırır. Burada tek bir kayıt megabaytlar tutar ve saklama kalemi ötekileri
gölgeler. İlk vaka bir **nesne deposu** (object storage) servisidir: istemci bir anahtarla ikili bir
gövde yazar, sonra aynı anahtarla okur. Ölçülecek iki karar var — **parçalı yüklemenin** (multipart
upload) fazladan gönderdiği bayt ve verinin kaç kopya tutulacağı. Bu dersin **dayanıklılığı
(veri)** verinin kaybolmamasıdır; Dayanıklılık ve Güvenilirlik kursunun dayanıklılığı hizmetin
ayakta kalmasıydı — bir depo ayakta olup veri kaybedebilir.

## Kısıtlar

İşlevsel gereksinim: anahtarla nesne yazma, okuma, silme, önek listeleme; büyük nesnelerde parça
parça gönderme, sonda birleştirme, yarım kalanı sürdürme.

İşlevsel olmayan gereksinim, sayıyla: nesne başına fazladan gönderilen bayt — yeniden gönderim ve
parça ek yükü — nesne boyunun yüzde **2**'sini geçmez; yıllık kaybolan nesne **500**'ün altında
kalır; saklanan bayt ham verinin **1,5** katını aşmaz; küçük nesne okuması **tek** istekle
karşılanır.

Kapsam daraltması: erişim denetimi ve imza doğrulama (Backend müfredatının Kimlik ve Yetki kursu),
sürümleme, yaşam döngüsü, çapraz bölge kopya ve içerikte arama tasarlanmaz.

## Varsayımlar

| Kod | Varsayım | Değer | Gerekçe |
|---|---|---|---|
| ND1 | günlük yüklenen nesne | 1.200.000 | uçların günlük toplamı |
| ND2 | küçük nesnelerin payı | 0,92 | küçük ekler sayıca hâkim |
| ND3 | küçük nesne ortalama boyu | 180 KB | belge ve küçük görsel |
| ND4 | büyük nesne ortalama boyu | 90 MB | kayıt ve yedek dosyası |
| ND5 | nesne başına ömür boyu okuma | 4 | nesne birkaç kez okunur |
| ND6 | tepe çarpanı | 3 | tepe saatin gün ortalamasına oranı |
| ND7 | kesintiler arası gönderilen bayt | 250 MB | uçlar hareketli ağlarda |
| ND8 | parça başına ek yük | 8 KB | başlık, imza, parça defteri kaydı |
| ND9 | yıllık düğüm kayıp olasılığı | 0,01 | donanım ve işletim kaynaklı |
| ND10 | saklama süresi | 365 gün | sözleşme yıllık dönem üzerinden |
| ND11 | nesne üstverisi kaydı | 400 bayt | anahtar, boy, sağlama, yerleşim |
| ND12 | en yavaş yükleme ucu | 1 Mbit/s | vale anahtarı ömrünün alt sınırı |

## Ölçek

```js
// nesne-olcek.mjs — ND tablosundan cikan olcek hesabi; hepsi aritmetiktir
const ND = { nesne: 1_200_000, kucukPay: 0.92, kucukBayt: 180e3, buyukBayt: 90e6, okuma: 4,
  tepe: 3, kesintiBayt: 250e6, parcaEkYuk: 8192, saklamaGun: 365, ustveriBayt: 400,
  parcaBoyu: 2e6, yavasUcMbit: 1 };
const GUN = 86_400;
const ortBayt = ND.kucukPay * ND.kucukBayt + (1 - ND.kucukPay) * ND.buyukBayt;
const gunlukBayt = ND.nesne * ortBayt, nesneSn = ND.nesne / GUN;
const parcaSn = nesneSn * ((1 - ND.kucukPay) * Math.ceil(ND.buyukBayt / ND.parcaBoyu) + ND.kucukPay);

const r = {
  "buyuk nesnelerin bayt payi": ((1 - ND.kucukPay) * ND.buyukBayt) / ortBayt,
  "gunluk yuklenen TB": gunlukBayt / 1e12,
  "ham saklanan PB": (gunlukBayt * ND.saklamaGun) / 1e15,
  "tepe yukleme nesne/s": nesneSn * ND.tepe,
  "tepe parca istegi/s": parcaSn * ND.tepe,
  "parcalamanin istek carpani": parcaSn / nesneSn,
  "tepe yukleme Mbit/s": (gunlukBayt / GUN) * ND.tepe * 8 / 1e6,
  "tepe okuma Mbit/s": (gunlukBayt / GUN) * ND.okuma * ND.tepe * 8 / 1e6,
  "ustveri saklanan GB": (ND.nesne * ND.saklamaGun * ND.ustveriBayt) / 1e9,
  "nesne/ustveri hacim orani": ortBayt / ND.ustveriBayt,
};
for (const [ad, d] of Object.entries(r))
  console.log(ad.padEnd(28) + (Number.isInteger(d) ? String(d) : d.toFixed(2)).padStart(10));

const en = (k) => Math.sqrt(2 * ND.parcaEkYuk * ND.kesintiBayt * k);   // en dusuk fazladan bayt
console.log(`\nen iyi parca boyu = karekok(2 * ek yuk * kesinti araligi) = ${(en(1) / 1e6).toFixed(2)} MB` +
  `; ND7 x2 -> ${(en(2) / 1e6).toFixed(2)} MB, ND7 x0.5 -> ${(en(0.5) / 1e6).toFixed(2)} MB`);
console.log(`en yavas ucta 2 MB parca ${(ND.parcaBoyu * 8) / (ND.yavasUcMbit * 1e6)} s -> ` +
  `vale anahtari omru 60 s (x${(60 / ((ND.parcaBoyu * 8) / (ND.yavasUcMbit * 1e6))).toFixed(2)} pay)`);
```

```
buyuk nesnelerin bayt payi        0.98
gunluk yuklenen TB                8.84
ham saklanan PB                   3.23
tepe yukleme nesne/s             41.67
tepe parca istegi/s             188.33
parcalamanin istek carpani        4.52
tepe yukleme Mbit/s            2455.20
tepe okuma Mbit/s              9820.80
ustveri saklanan GB             175.20
nesne/ustveri hacim orani     18414.00

en iyi parca boyu = karekok(2 * ek yuk * kesinti araligi) = 2.02 MB; ND7 x2 -> 2.86 MB, ND7 x0.5 -> 1.43 MB
en yavas ucta 2 MB parca 16 s -> vale anahtari omru 60 s (x3.75 pay)
```

Bu sayılar **hesap** sınıfındadır ve dördü tasarımı belirliyor. Nesnelerin yüzde 8'i baytların
yüzde 98'ini taşıyor, bu yüzden iki boy sınıfı ayrı tasarlanır. Üstveri hacmi nesne hacminin
18.414'te biri: 3,23 PB'a karşılık 175,20 GB. Parçalama istek sayısını 4,52 katına çıkarıyor:
41,67 nesne yüklemesi tepe uçta 188,33 parça isteği. Tepe okuma çıkışı 9820,80 Mbit/s — baskın
kalem istek değil, bant genişliği ve saklamadır.

## Parça Boyu

Kesinti bir akışı kestiğinde o ana kadar gönderilmiş baytlar boşa gitmiştir. Parça küçüldükçe boşa
giden bayt azalır, ama ek yük (ND8) her parçada ödenir. İki eğrinin toplamı ölçülür.

```js
// parca-boyu.mjs — surec ici model: 90 MB'lik nesnenin parcali yuklenmesi. Ag yok, dosya yok;
// kesinti, gonderilen bayt uzerinde ustel araliklarla uretilir. Tohum gorunur, uretec kendi yazilir.
const NESNE = 90e6, KESINTI = 250e6, EK = 8192, KOSU = 5000, TOHUM = 20260730, L = 1 / KESINTI;
let durum = TOHUM;                                  // dogrusal eslesik uretec
const rast = () => { durum = (durum * 1103515245 + 12345) % 2147483648; return durum / 2147483648; };
const aralik = () => -Math.log(1 - rast()) / L;     // kesintiye kadar gonderilen bayt

function yukle(boy) {
  let gonderilen = 0;
  for (let kalan = NESNE; kalan > 0; kalan -= boy) {
    const p = Math.min(boy, kalan);
    for (;;) {
      gonderilen += EK;                             // her deneme bir istek turu
      const g = aralik();
      if (g >= p) { gonderilen += p; break; }
      gonderilen += g;                              // kesildi: bu parca bastan gonderilir
    }
  }
  return gonderilen;
}

function beklenen(boy) {                            // ayni bolumleme uzerinde kapali bicim
  let t = 0;
  for (let kalan = NESNE; kalan > 0; kalan -= boy) {
    const p = Math.min(boy, kalan);
    t += (Math.exp(L * p) - 1) / L + EK * Math.exp(L * p);
  }
  return t;
}

console.log(`model: ${KOSU} yukleme, nesne ${NESNE / 1e6} MB, kesinti araligi ${KESINTI / 1e6} MB, ` +
  `parca ek yuku ${EK} bayt, tohum ${TOHUM}\n\n` + "parca".padStart(9) + "parca sayisi".padStart(14) +
  "gonderilen MB".padStart(15) + "olculen oran".padStart(14) + "beklenen oran".padStart(15));
for (const b of [256e3, 1e6, 2e6, 4e6, 16e6, NESNE]) {
  let t = 0;
  for (let i = 0; i < KOSU; i += 1) t += yukle(b);
  const ort = t / KOSU;
  console.log((b === NESNE ? "tek akis" : `${(b / 1e6).toFixed(2)} MB`).padStart(9) +
    String(Math.ceil(NESNE / b)).padStart(14) + (ort / 1e6).toFixed(2).padStart(15) +
    (ort / NESNE).toFixed(4).padStart(14) + (beklenen(b) / NESNE).toFixed(4).padStart(15));
}
```

```
model: 5000 yukleme, nesne 90 MB, kesinti araligi 250 MB, parca ek yuku 8192 bayt, tohum 20260730

    parca  parca sayisi  gonderilen MB  olculen oran  beklenen oran
  0.26 MB           352          92.94        1.0326         1.0326
  1.00 MB            90          90.91        1.0101         1.0102
  2.00 MB            45          90.68        1.0075         1.0081
  4.00 MB            23          90.90        1.0100         1.0101
 16.00 MB             6          93.11        1.0346         1.0319
 tek akis             1         108.14        1.2015         1.2038
```

Ölçülen oran bu koşumda geçerli bir **ölçüm**, beklenen oran koşumdan bağımsız bir **hesaptır**;
ikisi dört basamağın üçünde örtüşüyor. Yüzde 2 kısıtı eğrinin iki ucunu kesiyor: 256 KB'da
fazladan bayt yüzde 3,26 ve sebebi yeniden gönderim değil, 352 parçanın ek yüküdür; 16 MB'da yüzde
3,46 ve sebep yeniden gönderimdir. Kısıtı yalnız 1 MB ile 4 MB arası karşılıyor, en iyi nokta 2
MB'da ve kapalı çözümle aynı yerde. Tek akışta 90 MB için ortalama 108,14 MB gidiyor; bu oran nesne
büyüdükçe kötüleşir çünkü beklenen bayt nesne boyuyla üstel büyür.

**Duyarlılık:** ND7 iki katına çıkarsa en iyi parça boyu 2,86 MB'a, yarıya inerse 1,43 MB'a kayar;
ND7 dört kat değiştiğinde parça boyu iki kat. Karar ND7'ye zayıf bağlı, 2 MB geniş bir aralıkta
savunulabilir.

## Tasarım

Yükleme yolu **vale anahtarı kalıbına** dayanır (Dayanıklılık ve Güvenilirlik kursunun Dağıtık
Doğruluk konusu). Servis baytları taşımaz; istemciye tek bir parçaya yazma yetkisi veren süreli bir
anahtar döner. Anahtarın kapsamı bir yükleme kimliği ile bir parça numarası, ömrü 60 saniyedir — en
yavaş uçta 2 MB'lık parça 16 saniye sürdüğü için 3,75 kat pay kalır. Bu seçim 2455,20 Mbit/s
yükleme trafiğini servis düğümlerinin dışında tutar. Parça yazma **etkisizdir** (aynı konu, Etkisiz
İşlemler); tekillik anahtarı aynı ikilidir, dolayısıyla istemci hangi parçanın gittiğinden emin
olmadan gönderebilir.

Üstveri deposu **anahtar–değer deposudur** (Veri Katmanı Ölçekleme kursunun Veri Dağıtımı konusu,
Depo Türleri) ve nesne anahtarının karmasına göre **parçalanır** (aynı konu, Parçalama). Aralık
değil karma seçilir: ortak önek altında toplanan anahtarlar aralık bölümlemesinde tek parçayı
ısıtır. Yarım kalan yüklemelerin parçalarını **zamanlayıcı–aracı–denetçi** kalıbı toplar (Uygulama
Katmanı ve Servis Etkileşimi kursunun Kuyruklar ve İş Akışları konusu); penceresi 7 gün.

**Bilerek kullanılmayan kalıp: önbellek.** Veri Katmanı Ölçekleme kursunun Önbellek Mimarisi
konusundaki yanında okuma buraya konmaz: bir nesne ömrü boyunca yalnız 4 kez okunuyor (ND5) ve
günlük 8,84 TB'ın kesrini tutacak katmanın maliyeti dört okumaya değmez. İkincisi **oturum
yapışkanlığıdır** (Trafik Katmanı kursunun Yük Dengeleme konusu): parça yazmaları durumsuzdur.

## Elenen Alternatif: Her Nesne Üç Kopya

En basit tasarım her nesneyi üç kopya tutmaktır. Alternatif **silme kodlamasıdır** (erasure
coding): nesne k veri parçasına bölünür, m eşlik parçası hesaplanır, k+m parçadan herhangi k tanesi
nesneyi geri verir.

```js
// dayaniklilik.mjs — kopya sayisi ile silme kodlamasinin saklama, kayip ve istek maliyeti.
// Kayiplar bagimsiz varsayilir (ND9); bu bir model kabuludur, olcum degil.
let P = 0.01;                                             // ND9
const N = 1_200_000 * 365, KUCUK = 180e3, EK = 8192;      // ND1xND10, ND3, ND8
const TEPE = (1_200_000 * 4 / 86_400) * 3 * 0.92;         // nesne-olcek.mjs: kucuk nesne okuma/s
const bin = (n, i) => { let t = 1; for (let j = 0; j < i; j += 1) t = (t * (n - j)) / (j + 1); return t; };
const kayip = (k, m) => {
  if (m === 0) return P ** k;                             // k kopyanin hepsi kaybolur
  let t = 0;                                              // k+m parcadan m+1 ve fazlasi kaybolur
  for (let i = m + 1; i <= k + m; i += 1) t += bin(k + m, i) * P ** i * (1 - P) ** (k + m - i);
  return t;
};

console.log(`ND9 = ${P}, saklanan nesne ${N.toLocaleString("tr-TR")}\n\n` + "kurulum".padEnd(14) +
  "saklama kati".padStart(13) + "kaybolan nesne/yil".padStart(19) + "okuma istegi".padStart(14) +
  "180 KB'de ek yuk".padStart(18));
for (const [ad, k, m] of [["3 kopya", 3, 0], ["silme (6,3)", 6, 3], ["silme (10,4)", 10, 4],
  ["silme (12,4)", 12, 4]])
  console.log(ad.padEnd(14) + (m === 0 ? k : (k + m) / k).toFixed(2).padStart(13) +
    (kayip(k, m) * N).toFixed(2).padStart(19) + String(m === 0 ? 1 : k).padStart(14) +
    `%${((((m === 0 ? k : k + m) * EK) / KUCUK) * 100).toFixed(1)}`.padStart(18));

const HAM = 3.23, BUYUK_PAY = 0.9775;                     // nesne-olcek.mjs
const karma = BUYUK_PAY * 1.4 + (1 - BUYUK_PAY) * 3;      // buyuk silme (10,4), kucuk 3 kopya
// GB-ay: dogrusal buyumede yil ortalamasi yil sonunun yarisi, 12 ayla carpilir -> x6
console.log(`\nyil sonu saklama: hepsi silme (10,4) ${(HAM * 1.4).toFixed(2)} PB, karma ` +
  `(kat ${karma.toFixed(3)}) ${(HAM * karma).toFixed(2)} PB, hepsi 3 kopya ${(HAM * 3).toFixed(2)} PB`);
console.log(`karmanin fazlasi ${(HAM * (karma - 1.4) * 6e6).toFixed(0)} GB-ay; kucuk nesnede tepe ` +
  `parca istegi/s 3 kopya ${TEPE.toFixed(2)}, silme (10,4) ${(TEPE * 10).toFixed(2)}\n`);
for (const p of [0.005, 0.01, 0.02, 0.04]) {
  P = p;
  console.log(`ND9=${p} -> 3 kopya ${kayip(3, 0).toExponential(2)}, silme (10,4) ` +
    `${kayip(10, 4).toExponential(2)}, oran ${(kayip(3, 0) / kayip(10, 4)).toFixed(2)}`);
}
```

```
ND9 = 0.01, saklanan nesne 438.000.000

kurulum        saklama kati kaybolan nesne/yil  okuma istegi  180 KB'de ek yuk
3 kopya                3.00             438.00             1             %13.7
silme (6,3)            1.50             530.17             6             %41.0
silme (10,4)           1.40              81.33            10             %63.7
silme (12,4)           1.33             174.51            12             %72.8

yil sonu saklama: hepsi silme (10,4) 4.52 PB, karma (kat 1.436) 4.64 PB, hepsi 3 kopya 9.69 PB
karmanin fazlasi 697680 GB-ay; kucuk nesnede tepe parca istegi/s 3 kopya 153.33, silme (10,4) 1533.33

ND9=0.005 -> 3 kopya 1.25e-7, silme (10,4) 6.03e-9, oran 20.74
ND9=0.01 -> 3 kopya 1.00e-6, silme (10,4) 1.86e-7, oran 5.39
ND9=0.02 -> 3 kopya 8.00e-6, silme (10,4) 5.51e-6, oran 1.45
ND9=0.04 -> 3 kopya 6.40e-5, silme (10,4) 1.51e-4, oran 0.42
```

Üç kopya iki sayıda birden eleniyor. Saklama kısıtı 1,50 katken üç kopyanın katı 3,00; silme
(10,4) 1,40 ile altında kalıyor ve dayanıklılıkta da kazanıyor: yılda 438 nesne yerine 81,33.
Silme (6,3) yıllık kaybı 530,17 ile "500'ün altında" kısıtını çiğniyor; silme (12,4) saklamada en
ucuzu ama kaybı (10,4)'ün iki katından fazla.

Alternatifin kazandığı yer küçük nesnededir. Silme (10,4) 180 KB'lık nesneyi 18 KB'lık on dört
parçaya bölüyor: ek yük nesnenin yüzde 63,7'sine çıkıyor, okuma on istek gerektiriyor — tepe uçta
153,33 yerine 1533,33 parça isteği, yani "tek istekle karşılanır" kısıtının çiğnenmesi. Seçim bu
yüzden karmadır: küçük nesne üç kopya, büyük nesne silme (10,4), kat 1,436.

**Hangi kısıt değişirse alternatif kazanır:** ND9 binde beşe inerse kodlamanın üstünlüğü 20,74 kata
çıkar; yüzde 2'de 1,45'e, yüzde 4'te 0,42'ye düşer — düğüm kaybı sıklaştığında üç kopya öne geçer,
çünkü on dört parçanın üçünü değil kopyaların tamamının kaybını gerektirir. Bağımsız kayıp bir
model kabulüdür; kayıplar ilişkiliyse iki sütun da iyimserdir.

## Arıza Davranışı ve Feda Edilen

Üstveri deposunun bir parçası düştüğünde o karma aralığında yeni yükleme başlatılamaz ve
birleştirme yapılamaz; ama sürmekte olan parça yazmaları vale anahtarıyla doğrudan depoya gittiği
için devam eder. Bu, **zarif bozulmadır** (Dayanıklılık ve Güvenilirlik kursunun Arıza Yalıtımı
konusu): yükleme durmaz, yalnız tamamlanamaz ve istemci 7 günlük pencere içinde tamamlayabilir. Bir
depolama düğümü kaybında silme (10,4) nesnesi 14 parçadan 13'üyle okunur; onarım k = 10 parça
okuduğu için trafiği nesne boyu kadardır. Parça isteği tepe hızı 188,33/s olduğundan yükleme yoluna
**kısıtlama** (aynı konu) bu hızın üstünde bir eşikle konur.

**Feda edilen:** küçük nesnelerde saklama katı 3'te bırakıldı. Her şey kodlansaydı yıl sonu 4,52
PB olurdu, karma seçim 4,64 PB: yılda 697.680 GB-ay fazladan saklama — küçük nesne okumasını
1533,33 yerine 153,33 parça isteğinde tutmanın bedeli.

## Özet

- Nesnelerin yüzde 8'i baytların yüzde 98'ini taşıyor; iki boy sınıfı ayrı tasarlanır ve parçalı
  yükleme istek sayısını 4,52 katına çıkarır: tepe uçta 188,33 parça isteği.
- Parça boyu bir çukurun dibinden seçilir: fazladan bayt oranı 256 KB'da 1,0326, 2 MB'da 1,0075,
  16 MB'da 1,0346, tek akışta 1,2015 ve en iyi nokta karekök(2 × ek yük × kesinti aralığı)
  formülüyle aynı yerde.
- Üç kopya iki sayıda birden elenir: saklama katı 3,00'e karşı 1,40, yıllık kayıp 438'e karşı
  81,33 nesne; ama küçük nesnede kodlama okumayı 153,33'ten 1533,33 isteğe çıkardığı için orada üç
  kopya kazanır.
- Seçim ND9'a bağlıdır: kayıp olasılığı yüzde 4'e çıkarsa oran 0,42 olur, üç kopya öne geçer.

## Sonraki Adım

Bu vakada nesne anlamsız bir bayt dizisiydi: yazıldığı gibi saklandı, okunduğu gibi verildi,
içeriğine bakılmadı. Sonraki vaka bu varsayımı kaldırır: yüklenen dosyanın birden çok
temsili üretilir ve hangisinin verileceği isteği yapanın o andaki koşullarına göre belirlenir. Soru
şuna dönüşür: aynı içerik kaç biçimde tutulur, bunları üretmenin işlemci maliyeti ile sakladıkları
bayt nasıl karşılaştırılır ve fazladan bir biçim ne zaman israftır.
