CQRS ve okuma/yazma ayrımı
CQRS nedir
CQRS (Command Query Responsibility Segregation - Komut Sorgusu Sorumluluk Ayrımı), veri modelini ve yazmadan (komutlar) ve okumadan (sorgular) sorumlu bileşenleri ayıran mimari bir yaklaşımdır.
Fikir: devlet değişim süreci geçerli değişmezler ve işlemler için optimize edilmiştir ve hızlı, hedefli projeksiyonlar ve ölçeklendirme için okuma.
Anahtar> Komutlar durumu değiştirir ve işlemin sonucunu döndürür. İstekler sadece okunur ve hiçbir yan etkisi yoktur.
Neden buna ihtiyacın var
Okuma performansı: Belirli senaryolar için materyalize projeksiyonlar (kasetler, raporlar, kataloglar).
Kritik yol kararlılığı:'ağır "birleştirmelerden ve agregalardan izole edilmiş kayıt.
Depolama seçimi özgürlüğü: Yazmak için OLTP, okumak için OLAP/önbellek/arama motorları.
Hızlandırılmış evrim: İşlemleri "kırma" riski olmadan yeni görünümler ekleyin.
Gözlemlenebilirlik ve denetim (özellikle Olay Kaynağı ile birlikte): durumu kurtarmak ve tekrarlamak daha kolaydır.
Ne zaman uygulanacak (ve ne zaman değil)
Uygunsa:- Farklı veri dilimleri ve karmaşık toplama ile okumalar geçerlidir.
- Kritik kayıt yolu ince ve öngörülebilir olmalıdır.
- Okuma ve yazma için farklı SLO/SLA'lar gereklidir.
- Alan yazma mantığının analitik/arama ihtiyaçlarından yalıtılması gereklidir.
- Etki alanı basit, yük düşük; CRUD başa çıkıyor.
- Okuma ve yazma arasındaki güçlü tutarlılık tüm senaryolar için zorunludur.
- Ekip deneyimsiz ve operasyonel karmaşıklık kabul edilemez.
Temel kavramlar
Command - Durumu değiştirmeyi amaçlar ('CreateOrder', 'CapturePayment'). Değişmezleri kontrol eder.
Sorgu-Verileri alır ('GetOrderById', 'ListUserTransactions'). Yan etkisi yok.
Kayıt modeli: agregalar/değişmezler/işlemler; depolama - ilişkisel/anahtar-değer/olay günlüğü.
Okuma (projeksiyon) modeli: maddeleşmiş tablolar/indeksler/önbellek, eşzamansız olarak senkronize edilir.
Tutarlılık: Genellikle kayıt ve okuma arasında nihai; Kritik yollar - yazma modelinden doğrudan okuma yoluyla.
Mimari (iskelet)
1. Yazma hizmeti: komutları kabul eder, değişmeyenleri doğrular, değişiklikleri yakalar (veritabanı veya olaylar).
2. Outbox/CDC: Değişiklik gerçeğinin garantili yayını.
3. Projeksiyon işlemcileri: Olayları/CDC'yi dinleyin ve okunan modelleri güncelleyin.
4. Okuma hizmeti: materyalize görünümlerden/önbelleklerden/aramalardan sorgular sunar.
5. Sagalar/orkestrasyon: çapraz agrega süreçlerini koordine eder.
6. Gözlemlenebilirlik: projeksiyon gecikmesi, başarılı uygulamaların yüzdesi, DLQ.
Kayıt Modeli Tasarlamak
Agregalar: açık işlem sınırları (örneğin, 'Sipariş', 'Ödeme', 'Kullanıcı Bakiyesi').
Değişmezler: resmileştirmek (parasal miktarlar ≥ 0, benzersizlik, limitler).
Komutlar anahtarla idempotenttir (örneğin, 'idempotency _ key').
İşlemler minimal kapsamdadır; Dış yan etkiler - dış kutu aracılığıyla.
Komut Örneği (Pseudo-JSON)
json
{
"command": "CapturePayment",
"payment_id": "pay_123",
"amount": 1000,
"currency": "EUR",
"idempotency_key": "k-789",
"trace_id": "t-abc"
}
Okuma Modeli Tasarlamak
Sorgulardan başlayın: Hangi ekranlara/raporlara ihtiyaç var?
Denormalleştirme kabul edilebilir: okuma modeli - "optimize edilmiş önbellek".
Farklı görevler için çeşitli projeksiyonlar: arama (OpenSearch), raporlar (sütunlu depolama), kartlar (KV/Redis).
TTL ve yeniden birleştirme: projeksiyonlar kaynaktan kurtarılabilmelidir (olay tekrarı/anlık görüntüler).
Tutarlılık ve UX
Nihai tutarlılık: Arayüz eski verileri kısa bir süre için görüntüleyebilir.
UX kalıpları: "Veriler güncellenir"..., iyimser UI, senkronizasyon göstergeleri, onaylanana kadar tehlikeli eylemleri engelleme.
Güçlü tutarlılık gerektiren işlemler için (örneğin, yazmadan önce doğru bir denge göstermek), doğrudan yazma modelinden okuyun.
CQRS ve Olay Kaynak Kullanımı (isteğe bağlı)
Event Sourcing (ES), olayları saklar ve toplamın durumu, evrişimlerinin sonucudur.
CQRS + ES paketi, ideal bir denetim ve projeksiyonların kolay bir şekilde yeniden birleştirilmesini sağlar, ancak karmaşıklığı artırır.
Alternatif: düzenli OLTP veritabanı + giden/CDC - projeksiyonlar.
Replikasyon: Giden kutusu ve CDC
Giden kutusu (bir işlemde): etki alanı değişiklikleri yazma + giden kutusuna bir olay yazma; Yayıncı lastiğe teslimat yapar.
CDC: veritabanı günlüğünden okuma (Debezium, vb.) - etki alanı olaylarına dönüşüm.
Garantiler: Varsayılan olarak en az bir kez, tüketiciler ve projeksiyonlar idempotent olmalıdır.
Depolama seçimi
Yazma: işlemler için ilişkisel (PostgreSQL/MySQL); KV/Belge - değişmezlerin basit olduğu yer.
Okuyun:- KV/Redis - kartlar ve hızlı anahtar okumaları;
- Arama (OpenSearch/Elasticsearch) - arama/filtreler/fasetler;
- Sütun (ClickHouse/BigQuery) - raporlar;
- CDN'de önbellek - genel dizinler/içerik.
Entegrasyon kalıpları
API katmanı: 'komutlar've' sorgular 'için ayrı uç noktalar/hizmetler.
Idempotency: başlık/gövdedeki operasyonun anahtarı; TTL ile son anahtarların depolanması.
Sagalar/orkestrasyon: zaman aşımları, telafiler, adım tekrarlanabilirliği.
Backpressure-Projeksiyon işlemcilerinin paralelliğini sınırlar.
Gözlemlenebilirlik
Yazma metrikleri: p95/99 komut gecikmeleri, başarılı işlemlerin yüzdesi, doğrulama hataları.
Metrikleri okuyun: p95/99 istekleri, isabet oranı önbelleği, arama kümesine yükleyin.
Projeksiyon gecikmesi (zaman ve mesajlar), DLQ oranı, veri tekilleştirme yüzdesi.
Tracing: 'trace _ id' ^ outbbox komutundan geçer.
Güvenlik ve uyumluluk
Hak ayrımı: yazma ve okuma için farklı kapsamlar/roller; En az ayrıcalık ilkesi.
PII/PCI: projeksiyonlarda en aza indirmek; at-rest/in-flight şifreleme; maskeleme.
Denetim: Düzeltme ekibi, aktör, sonuç, 'trace _ id'; Kritik alanlar için WORM arşivleri (ödemeler, KYC).
Test etme
Sözleşme testleri: komutlar (hatalar, değişmezler) ve sorgular (formatlar/filtreler) için.
Projeksiyon testleri: bir dizi olay/CDC gönderin ve son okuma modelini kontrol edin.
Kaos/gecikme: projeksiyon işlemcilerine gecikme enjekte etmek; Gecikmede UX kontrolü.
Tekrarlanabilirlik: Stanttaki projeksiyonları anlık görüntülerden/günlükten yeniden bir araya getirme.
Göçler ve evrim
Yeni alanlar - olay/CDC'de katkı maddesi; okuma modelleri yeniden inşa edilir.
Devreleri yeniden tasarlarken çift yazma; Değişene kadar eski projeksiyonları tutun.
Sürüm oluşturma: 'v1'/' v2' olaylar ve bitiş noktaları, Sunset-plan.
Özellik bayrakları: kanarya boyunca yeni sorguların/projeksiyonların tanıtımı.
Anti-desenler
Basit CRUD hizmetlerinde "moda uğruna" CQRS.
Sabit eşzamanlı okuma-yazma bağımlılığı (izolasyonu ve kalıcılığı öldürür).
Herkes için bir dizin: heterojen sorguları tek bir okuma deposunda karıştırmak.
Projeksiyonlar idempotency yok - kopyalar ve tutarsızlıklar.
Kurtarılamaz projeksiyonlar (tekrar oynatma/anlık görüntü yok).
Domain örnekleri
Ödemeler (online hizmet)
Yazma: İşlem veritabanında 'Yetkilendirme', 'Yakalama', 'Geri Ödeme'; Giden kutusu 'ödeme yayınlar. '.
Okuyun:- UI için Redis "ödeme kartı";
- Raporlama için ClickHouse;
- İşlemleri aramak için OpenSearch.
- Kritik yol: 800 ms p95 ≤ yetkilendirme; UI için tutarlılığı okuyun - nihai (2-3 s'ye kadar).
KYC
Yazma: durumu başlatmak/güncellemek için komutlar; Güvenli bir veritabanında PII depolama.
Okuyun: PII olmadan durumların hafif projeksiyonu; Gerekirse PII noktasal olarak sıkılır.
Güvenlik: okuma durumu ve belgelere erişim konusunda farklı kapsamlar.
Bilançolar (iGaming/Finans)
Yaz: 'UserBalance' atomik artışlar/azalmalar ile toplanır; Ameliyat için idempotent anahtarlar.
Oku: "hızlı denge" için önbellek; yazma için - yazıdan doğrudan okuma (katı tutarlılık).
Saga: Mevduat/sonuçlar olaylar tarafından koordine edilir, başarısızlık durumunda - tazminat.
Uygulama kontrol listesi
- Yazma modelinin toplamları ve değişmezleri vurgulanır.
- Anahtar sorgular tanımlanır ve bunlar için projeksiyonlar tasarlanır.
- Outbox/CDC ve idempotent projeksiyon işlemcileri yapılandırılmıştır.
- Bir anlık görüntü/tekrar oynatma planı var.
- SLO: komut gecikmesi, projeksiyon gecikmesi, okuma/yazma kullanılabilirliği ayrı ayrı.
- Ayrılmış erişim hakları ve uygulanan veri şifreleme.
- DLQ uyarıları/gecikme/veri tekilleştirme hataları.
- Testler: Sözleşmeler, Projeksiyonlar, Kaos, Tekrar.
SSS
CQRS için Event Sourcing zorunlu mu?
Hayır. Düzenli bir veritabanı + giden kutusu/CDC üzerine inşa edebilirsiniz.
Desynchronization ile nasıl başa çıkılır?
Açıkça UX tasarlayın, projeksiyon gecikmesini ölçün, kritik işlemlerin yazıdan okunmasına izin verin.
Aynı serviste hem yazmak hem de okumak mümkün mü?
Evet, fiziksel ayırma isteğe bağlıdır; Sorumlulukların mantıksal olarak bölünmesi zorunludur.
Peki ya agregalar arasındaki işlemler?
Destanlar ve olaylar aracılığıyla; Mümkünse dağıtılmış işlemlerden kaçının.
Sonuç
CQRS elleri çözer: net değişmezlere sahip ince, güvenilir bir yazma yolu ve materyalize projeksiyonlardan hızlı, hedefli okumalar. Bu, verimliliği arttırır, evrimi basitleştirir ve sistemi strese karşı daha esnek hale getirir - tutarlılık, gözlemlenebilirlik ve göçler disiplinli ise.