engineering
Dağıtık Sistemlerde Veri Bütünlüğü ve Debezium Kararı
14 Aralık 2025 · 4 dk okuma
Birden Çok Yer, Tek Gerçek
Dağıtık sistem, en sade haliyle, farklı yerlerdeki parçaların tek bir ağmış gibi davranması demek. Aramayı MeiliSearch’te yaparsın ama asıl veri PostgreSQL’de durur. Pazarlama aracın kendi MySQL’inden çalışır. Web siten bir veritabanında, muhaseben başka birinde. Hepsi aynı ürün için birlikte çalışır.
Sorun da tam burada başlar: bu parçaların hepsi aynı gerçeği görmek zorunda. Birinde değişen veri, ötekinde de değişmeli. Yoksa kullanıcı bir yerde güncellediği şeyi başka yerde eski haliyle görür. Bu yazı, o tutarlılığı sağlamak için çektiğim çileyi ve sonunda oturduğum çözümü anlatıyor.

Tutarlılığı Sağlamanın Zor Yolları
Veritabanları arası senkronu çözmek için akla ilk gelen yöntemler, çoğu zaman insanı daha derin bir çukura sokar.
Polling. Bir worker belli aralıklarla çalışsın, gidip verileri güncellesin. Kulağa makul geliyor, ama veritabanı büyüdükçe bu sorgular full table scan yapıp CPU’yu kilitler. Üstelik asla gerçek zamanlı olmaz; aradaki boşluk hep büyür. Bir de silinen kayıtları yakalayamazsın, çünkü select ile bir satırın yokluğunu göremezsin. Bu da seni ikinci bir kontrol katmanı yazmaya zorlar.
Spagetti kod ve bağımlılık. Senkron mantığını uygulama koduna gömmek. Diyelim UserService var, kullanıcı profilini güncelleyince ElasticSearch’ü de güncellemen gerekiyor. Metodun içine ElasticSearch çağrısı eklersin. Artık UserService sadece kullanıcı işi yapmaz; ElasticSearch yavaşsa “Güncelle” butonu yavaşlar, o servis hata dönerse buton bozulur. Aslında işini yapmıştı, ama yapıştırdığın bağımlılık onu rehin aldı.
Dual write laneti. Dağıtık sistemlerin en sinsi düşmanı. “Kullanıcıyı veritabanına yazarım, hemen sonra RabbitMQ’ya bir event atarım” dersin. İki ayrı yere yazıyorsun ve ikisinin birden başarılı olacağına dair hiçbir garantin yok. Kuyruk o an çökerse, veri veritabanında durur ama event hiç gitmez. Kuyruk geri geldiğinde de o veriyi bilmez. Eksik veri, çift veri, sessiz tutarsızlık.

Race condition. Nadir sanılır ama art arda bağlı event zincirlerinde, asenkron yapılarda sıra karışır. İki ayrı yerden fazlasında güncelleme olunca, biri henüz oluşmadan üstüne yazılmaya çalışılır ve hata alırsın.
Çözüm: “Ne Değişti?” Diye Sormayı Bırakmak
Bu sorunların hepsinin altında tek bir yanlış refleks var: veritabanına sürekli “sende ne değişti?” diye sormak.
Oysa veritabanı her işlemini zaten bir yere not ediyor. PostgreSQL buna WAL (Write Ahead Log), MySQL Binlog diyor. Veritabanı çökse bile bu günlükler sayesinde ayağa kalkıyor. Çözüm tam burada: uygulama koduna dokunmadan, veritabanına ek sorgu yüklemeden, doğrudan bu günlükleri dinlemek. Buna Change Data Capture, kısaca CDC diyoruz.
Peki bu logları kim okuyacak? Ham log dosyasını ayrıştırmak başlı başına bir mühendislik işi. İşte burada Debezium giriyor. Debezium kendini veritabanına bir replika gibi tanıtır; motor “şu satır eklendi, bu satır silindi” diye loga yazdığı an Debezium onu yakalar, standart bir JSON’a çevirip Apache Kafka’ya bırakır. (Bu arada sevdiğim bir laf: bir sorunu Kafka ile çözüyorsan, tebrikler, artık iki sorunun var.)
Bu mimariye geçince çilelere ne oluyor?
- Dual write biter. Artık “hem DB’ye yaz hem kuyruğa at” yok. Sadece DB’ye yazarsın, Debezium yazılanı garantili biçimde event’e çevirir. Outbox pattern’in temeli bu.
- Polling biter.
SELECT *yok, veritabanına ek yük yok. Log okumak veritabanı için neredeyse bedava. - Hard delete çözülür. Bir satırı sildiğinde loga “şu ID silindi” düşer; Debezium bunu da yakalar ve “bunu ElasticSearch’ten de sil” diye haber verir.
- Gerçek zamanlıya en yakın. Cron’un beş dakikalık gecikmesi yerine milisaniye mertebesinde.
Akış Nasıl İşliyor
Kafada canlanması için sade bir akış:
- Uygulama sadece PostgreSQL’e
INSERT INTO users...atar, işini bitirir. - PostgreSQL veriyi diske yazar ve WAL’a işler.
- Debezium WAL’daki bu değişikliği anında görür.
- Kafka’ya Debezium bunu bir mesaj olarak bırakır.
- Tüketiciler (ElasticSearch, cache, pazarlama aracı) o mesajı dinler ve veriyi kendine alır.
Böylece o karmaşık orkestra, tek bir şeften, yani veritabanı loglarından talimat alarak senkron çalmaya başlar.

Dürüst olmam gereken yer şu: bedava peynir yok. Debezium harika bir araç, ama beraberinde Kafka yönetimini, şema değişikliklerini ve operasyonel bir maliyeti getiriyor. Cron job yazmak Kafka yönetmekten kolaydır. Ama ölçeklenen bir sistemde veri tutarlılığı uykunu kaçırıyorsa, bu bedel gece rahat uyumanın yanında küçük kalıyor.
Mükemmel Kod Yoktur, Yönetilebilir Kaos Vardır
Dağıtık sistem kurmak, lego birleştirmeye benzemez. Lego’da parçalar sabittir; yazılımda parçalar sürekli hareket eder, ağlar kopar, sunucular nazlanır. Kıdem dediğimiz şey de aslında prod’da patlayan veritabanlarının başında geçirdiğimiz gecelerin toplamı. Bu süreçte öğrendiğim en net şey şu: mükemmel kod yoktur, yönetilebilir kaos vardır.
Debezium ve CDC, işte o kaosu yönetilebilir kılan, senkron işini spagetti koddan kurtarıp tek bir gerçeklik kaynağına bağlayan bir yaklaşım. Karmaşıklığın ürünü nasıl içten içe kemirdiğini başka bir yazıda anlatmıştım; buradaki mesele de aynı: sadeliği bir yöntemle korumak.
Mimari kararlarımda önceliğim hiçbir zaman sadece günü kurtarmak değil, gece rahat uyumak oldu. Çünkü iyi mühendislik sadece kodun çalışması değil, o kodu yaşatanların da huzurlu olması demek. Sağlıklı, tutarlı ve bol commit’li günler.
Yazının İngilizce versiyonuna bu linkten ulaşabilirsin.