CQRS Pattern Nedir? Komut ve Sorgu Ayrımı Rehberi
Geleneksel uygulamalarda aynı model hem veri yazma hem veri okuma için kullanılır. CQRS, bu yaklaşımı kökünden değiştirir: yazan taraf ile okuyan tarafı birbirinden ayırır.
CQRS Temel Kavramı
CQRS (Command Query Responsibility Segregation), adından da anlaşılacağı gibi iki sorumluluğu ayırır:
- Command (Komut) — Veriyi değiştirir, sonuç döndürmez
- Query (Sorgu) — Veriyi okur, hiçbir şeyi değiştirmez
Kullanıcı İsteği
↓
┌─────────────────────┐
│ Yazma Tarafı │ ← Commands (SiparişOluştur, ÖdemeYap)
│ (Command Model) │
│ - İş kuralları │
│ - Validasyon │
│ - Event üretme │
└──────────┬──────────┘
│ Events
↓
┌─────────────────────┐
│ Okuma Tarafı │ ← Queries (SiparişleriListele, RaporAl)
│ (Query Model) │
│ - Sorguya optimize │
│ - Denormalize veri │
│ - Hızlı okuma │
└─────────────────────┘
Neden CQRS Kullanmalı?
1. Bağımsız Ölçekleme
Okuma ve yazma işlemleri genellikle çok farklı ölçeklerde gerçekleşir. Bir e-ticaret sitesinde okuma/yazma oranı genellikle 100:1'dir. CQRS ile okuma tarafını bağımsız ölçekleyebilirsiniz.
2. Farklı Veri Modelleri
Yazma için normalize veri (3NF), okuma için denormalize veri (sorguya optimize) kullanabilirsiniz.
Yazma modeli:
Sipariş → SiparişKalemi → Ürün → Kategori
Okuma modeli:
SiparişGörünümü { siparişId, müşteriAdı, ürünler[], toplam, durum }
3. Performans Optimizasyonu
Okuma tarafında karmaşık JOIN'ler yerine hazır, denormalize view'lar kullanılır. Sonuç: dramatik performans artışı.
4. Güvenlik
Yazma ve okuma arayüzleri ayrı olduğu için, her biri için farklı güvenlik politikaları uygulanabilir.
CQRS + Event Sourcing
CQRS, Event Sourcing ile birlikte kullanıldığında en güçlü halini alır:
Command → Event Store → Events → Projection → Read Model
- Kullanıcı bir komut gönderir
- Komut işlenir ve olaylar üretilir
- Olaylar Event Store'a yazılır
- Projection süreci olayları dinler
- Read model (görünüm tabloları) güncellenir
- Sorgular read model üzerinden çalışır
Pratik Örnekler
E-ticaret Sipariş Sistemi
Yazma tarafı:
SiparişOluştur { müşteriId, ürünler[], adres }
→ Validasyon: Stok yeterli mi? Müşteri aktif mi?
→ Event: SiparişOluşturuldu { ... }
Okuma tarafı:
SiparişleriGetir { müşteriId, sayfa, filtre }
→ Hazır denormalize tablodan oku
→ Sonuç: [{ siparişId, tarih, durum, toplam }]
Raporlama
CQRS'in en parlak olduğu alan raporlamadır. Raporlar için özel materialize view'lar oluşturabilirsiniz — ana veri modeline dokunmadan.
CQRS Bu Zaman Kullanılmalı?
✅ Uygun Senaryolar
- Yüksek okuma/yazma oranı farkı
- Karmaşık iş kuralları olan yazma tarafı
- Farklı sorgu gereksinimleri
- Event Sourcing kullanılan sistemler
- Raporlama yoğun uygulamalar
❌ Uygun Olmayan Senaryolar
- Basit CRUD uygulamaları
- Anlık tutarlılık gerektiren sistemler
- Küçük ekipler ve basit projeler
Eventual Consistency
CQRS'in en önemli ödünleşimi: yazma ve okuma modeli arasında gecikmeli tutarlılık (eventual consistency) olabilir. Yani bir kayıt yazıldıktan birkaç milisaniye/saniye sonra okuma tarafında görünür.
Bu çoğu uygulama için kabul edilebilir, ancak bazı durumlar (ör. banka hesap bakiyesi) için dikkatli olmak gerekir.
Sonuç
CQRS güçlü bir mimari desendir, ancak her derde deva değildir. Doğru bağlamda uygulandığında performans, ölçeklenebilirlik ve esneklik sağlar. Yanlış yerde uygulandığında gereksiz karmaşıklık getirir.
CQRS ve Event Sourcing'i pratik olarak öğrenmek için LabLudus platformundaki Architect kariyer yolundaki dağıtık sistem görevlerini tamamlayın. Yazılım Mimarisi 3.0 kitabında bu konuları derinlemesine inceliyoruz.