Blog
Mert Özen'in yazılım geliştirme, backend, frontend ve DevOps üzerine blog yazıları.
Bookstore Reposu ve Okuma Haritası: Kodu Nereden Alırım, Hangi Parça Hangi Seride?
Bookstore'un kodu tek bir GitHub reposunda duruyor: main referans uygulama, her seri series/<seri-slug> branch'i, her yazı <seri-slug>/NN tag'i. Bir yazının kodunu git switch --detach ile almayı, iki yazı arasındaki farkı git diff ile görmeyi, denemeleri kendi branch'inde yapmayı ve backend, frontend, mimari ve ekip lideri için okuma yollarını anlatıyoruz.
Bookstore'un Teknik Yapısı: Module'ler, Veri Modeli, Web API ve Angular İstemcisi
Bookstore'un referans uygulaması tek bir ASP.NET Core 10 API'sinde Catalog, Ordering ve Inventory module'lerini, her module için ayrı SQL schema'sı olan tek bir BookstoreContext'i, xUnit v3 integration testlerini ve Angular 22 istemcisini içerir. Module haritasını, veri modelini, endpoint'leri, eşzamanlı siparişte deadlock veren ilk stok kodunu ve onu düzelten koşullu UPDATE'i, Windows'ta çalıştırma adımlarını anlatıyoruz.
Bookstore Nedir? Sitedeki Serilerin Ortak Örnek Uygulaması: Ürün, Kullanıcılar ve İş Kuralları
Bookstore, sitedeki bütün serilerin aynı dünyada geçmesi için seçilmiş bir online kitapçıdır: bireysel satış, okul ve kütüphanelere Kurumsal Sipariş ve arka ofis. Altı rolü, katalogdan kargoya ana akışı, en az 20 adet, yüzde 10 kurumsal indirim, üst üste binmeyen kampanyalar, yarım kuruş yukarı yuvarlama gibi iş kurallarını, ürünün sayılarını ve ekibini anlatıyoruz.
Gerçek Sistemlerden Dersler: CRDT, Spanner TrueTime, CockroachDB HLC ve Jepsen
Gerçek sistemler belirsizlikle iki yoldan yaşar: koordinasyonu kaldıran veri tipleri (CRDT) ya da belirsizliği ölçüp bekleyen saatler (Spanner TrueTime, CockroachDB HLC). C# ile G-Counter, PN-Counter ve OR-Set yazıp CAP yazısındaki sepetin silinen kitabı geri getirme sorununu çözüyoruz; ε = 4 ms ile commit wait yaklaşık 9 ms sürüyor. Jepsen'in PostgreSQL ve etcd bulguları da garantiyi dokümantasyondan değil testten okumayı öğretiyor.
Distributed Lock, Lease ve Fencing Token: Kilit Neden Yetmez?
Süreli bir kilit (lease) tek başına doğruluk sağlamaz: kilidi alan process GC duraklamasında kalırsa lease dolar, başkası kilidi alır ve uyanan ilk process yine yazar. Gerçek Redis ve SQLite ile yapılan denemede eski rapor yenisinin üstüne yazılıyor; her kilitle artan bir fencing token'ı veritabanında WHERE token > LastToken ile kontrol edince eski yazma reddediliyor. Redlock tartışmasının iki tarafı ve veritabanının kendi mekanizmaları da yazıda.
Distributed Transaction ve Two-Phase Commit: Neden Microservice'lerde Kullanılmaz?
Two-phase commit (2PC), birden fazla participant'ın bir transaction'ı birlikte commit ya da abort etmesini sağlar, ama coordinator karar vermeden çökerse YES oyu veren participant'lar kilitleri tutarak bekler. System.Transactions'ın 2PC'si volatile participant'larla çalışıyor; ikinci durable participant ise macOS ve Linux'ta PlatformNotSupportedException veriyor. Microservice'lerde availability, coupling ve broker desteği yüzünden yerine saga ve outbox kullanılır.
Consensus ve Raft: Leader Election, Log Replication ve FLP Sonucu
Consensus, node'ların bir değer (ya da bir log sırası) üzerinde anlaşmasıdır; FLP sonucu asynchronous network'te tek bir çökmeye bile dayanıp her zaman sonlanan deterministik bir algoritma olmadığını söyler, Raft ise safety'yi term ve çoğunluk oylarıyla, liveness'ı rastgele timeout'larla sağlar. C# simülasyonunda leader çökünce 254 ms içinde yeni leader seçiliyor; sabit timeout'larda ise 2 saniyede term 13'e çıkıp hiç leader seçilemiyor.
CAP ve PACELC'i Doğru Okumak: "3'ten 2'sini Seç" Neden Yanlış?
CAP, partition sırasında linearizability (C) ile her sağlam node'un cevap vermesi (A) arasında seçim yapmak gerektiğini söyler; partition (P) seçilen bir özellik değil, başa gelen bir olaydır, bu yüzden "3'ten 2'si" özeti yanlıştır. PACELC, partition yokken de latency ile consistency arasında seçim yapıldığını ekler. Örnekte sepet partition'da silinen kitabı geri getiriyor, ödeme azınlık tarafında 503 dönüyor.
Consistency Model'leri: Linearizability, Sequential, Causal ve Eventual Consistency
Consistency model, bir sistemin hangi okuma/yazma geçmişlerine izin verdiğinin tanımıdır: linearizability gerçek zamana uyar, sequential yalnız her client'ın kendi sırasına, causal happens-before'a; eventual consistency ise yalnız sonunda aynı değere varmayı vaat eder. Küçük bir C# checker'ı beş geçmişi değerlendiriyor: yazma bittikten sonraki eski okuma linearizable değil ama sequential; kendi yazmasını görmemek ikisini de bozuyor.
Replication: Leader-Based, Multi-Leader, Leaderless ve Quorum
Replication üç topolojide yapılır: tek leader (basit, failover'da split brain riski), multi-leader (her bölgede yazma, conflict kaçınılmaz) ve leaderless quorum (R + W > N ise okuma son yazmayı görür). N=3 quorum simülasyonunda R=W=1 eski stok değerini döndürüyor, iki node düşünce sistem yazmayı reddediyor, ama "başarısız" yazma bir replica'da kalıp node'lar dönünce okunuyor.
Logical Clock'lar: Happens-Before, Lamport Clock ve Vector Clock
Lamport clock, happens-before ilişkisine uyan bir total order verir ama iki olayın concurrent olup olmadığını söyleyemez; vector clock bunu söyler, bedeli node sayısı kadar büyüyen bir timestamp'tir. C# ile LamportClock, VectorClock ve HybridLogicalClock yazıp xUnit ile test ediyoruz: Lamport'un 1 < 2 dediği iki olay vector clock'a göre concurrent, HLC ise 300 ms geride kalan sunucuda bile causality'yi koruyor.
Physical Clock'lar: NTP, Clock Drift, Leap Second ve Wall Clock'a Güvenmemek
Süre ölçmek için wall clock (DateTime.UtcNow) değil monotonic clock (Stopwatch, TimeProvider.GetTimestamp) kullanılır, olayları sıralamak için de fiziksel timestamp'e güvenilmez: NTP saati ileri geri atabilir, quartz saatler kayar. Örnekte NTP'nin 300 ms'lik düzeltmesi 200 ms'lik bir işi -97 ms gösteriyor ve 300 ms geride kalan bir sunucu yüzünden last-write-wins daha yeni fiyat güncellemesini sessizce siliyor.