CQRS'i ne zaman uygulamalı ve okuma/yazma modellerini nasıl senkronlamalıyım?
Soru
Uygulamamızda yazma operasyonları çok az (günde ~5.000 kayıt) ama okuma ve karmaşık raporlama çok yoğun (saniyede ~2.000 sorgu). İlişkisel DB raporlama sorguları yüzünden kilitleniyor. Yazma modelini (PostgreSQL) ve okuma modelini (Elasticsearch veya optimize Read-Replica SQL) tamamen ayırmak (CQRS) istiyoruz. İki model arası senkronizasyonu event-driven, gecikmesiz ve güvenilir nasıl sağlarım?
Cevap
Kısa cevap: Günde 5.000 yazma karşısında saniyede 2.000 okuma — bu asimetri gerçekten CQRS’e oynayan bir vaka. Ama en ucuz sürümle başla; doğrudan tam CQRS’e atlama.
Kısa cevap
Sorun net: ağır raporlama sorguları yazma yolunu da kilitliyor. Çoğu zaman bunu çözmek için tam bir mimari ayrışmaya gerek yok. Okuma modelini gerçekten Elasticsearch’e taşıyacaksan arama tarafının kendi maliyetleri de devreye girer; o hesabı edge n-gram kaydında ayrıca çıkarmıştım.
Neden
- Tam CQRS ancak sorgu şekilleri ayrıştığında hak eder. Ayrı bir okuma modeli (Elasticsearch ya da denormalize SQL) ancak sorgu şekilleri tek bir şemanın ikisini birden iyi servis edemeyeceği kadar ayrıştığında değer. Full-text arama, ağır agregasyon gibi ihtiyaçlar replica’nın da yetmediği noktada okuma modelini ayırmaya değer kılar.
- Dual-write kaçınılmaz olarak kayar. Uygulamadan iki store’a birden yazarsan iki taraf zamanla birbirinden ayrışır (drift) ve hangisinin doğru olduğunu söyleyemez hâle gelirsin.
- Okuma modeli her hâlükârda geride kalır. Okuma modeli yazmadan milisaniye-saniye geride kalır; eventual consistency bir kusur değil, bu mimarinin fiyatıdır.
Ne yapmalı
- Önce read-replica ekle. PostgreSQL’e bir veya birkaç read-replica koy ve tüm raporlama sorgularını oraya yönlendir. Yazma primary’de kalır, okuma replica’da; kilitlenme çoğu zaman sadece bununla biter. Bunu denemeden CQRS karmaşıklığını üstlenme.
- Modelleri event-driven senkronla. Yazma tarafı her değişiklikte event üretsin; bir projector bu event’leri tüketip okuma modelini güncellesin.
- Güvenilirlik için outbox pattern kullan. Event’i iş verisiyle aynı transaction içinde bir outbox tablosuna yaz, ayrı bir süreç onu yayınlasın — böylece “DB commit oldu ama event kayboldu” durumu olmaz.
- UI’ı eventual consistency’ye göre tasarla. Örneğin “kaydedildi” anında görünsün, listede biraz sonra belirsin. Okuma modelini daima yazma tarafının event’lerinden besle, asla iki store’a birden yazma.
Sonuç: Önce replica, raporlamayı oraya taşı. Tam CQRS’i yalnızca sorgu ihtiyaçları gerçekten ayrıştığında, outbox-tabanlı projeksiyonlarla kur — ve eklediğin karmaşıklığı bir maliyet olarak gör. “PostgreSQL bana yeter mi?” sorusunun cevabı çoğu yükte hâlâ evet; CQRS’e geçmeden önce onu sonuna kadar zorla.
İlgili Yazılar
Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.