CQRS və oxu/yazma bölgüsü
CQRS nədir
CQRS (Command Query Responsibility Segregation) - məlumat modelini və yazma (commands) və oxumağa (queries) cavabdeh olan komponentləri ayıran memarlıq yanaşmasıdır.
Fikir: vəziyyətin dəyişdirilməsi prosesi etibarlı invariantlar və əməliyyatlar üçün optimallaşdırılır, oxu isə sürətli, məqsədli proyeksiyalar və miqyaslandırma üçün optimallaşdırılır.
Niyə lazımdır
Oxuma performansı: konkret ssenarilər (lentlər, hesabatlar, kataloqlar) altında materiallaşdırılmış proyeksiyalar.
Kritik yolun sabitliyi: rekord «ağır» joins və aqreqatlardan təcrid olunur.
Saxlama seçimi azadlığı: Yazma üçün OLTP, oxu üçün OLAP/cache/axtarış motorları.
Sürətli təkamül: əməliyyatları «qırmaq» riski olmadan yeni təsəvvürlər əlavə edin.
Müşahidə və audit (xüsusilə Event Sourcing ilə birlikdə): vəziyyəti bərpa etmək və yenidən oynamaq daha asandır.
Nə zaman tətbiq olunur (və nə zaman deyil)
Əgər uyğun:- Müxtəlif məlumat kəsikləri və mürəkkəb aqreqasiya ilə oxunmalar üstünlük təşkil edir.
- Kritik yazma yolu incə və proqnozlaşdırıla bilən olmalıdır.
- Oxumaq və yazmaq üçün müxtəlif SLO/SLA lazımdır.
- Qeydlərin domen məntiqinin analitik/axtarış ehtiyaclarından təcrid edilməsi tələb olunur.
- Domain sadə, yük azdır; CRUD öhdəsindən gəlir.
- Bütün ssenarilər üçün oxu və yazı arasında güclü uyğunluq tələb olunur.
- Komanda təcrübəsiz və əməliyyat çətinliyi qəbuledilməzdir.
Əsas anlayışlar
Komanda (Command): vəziyyəti dəyişdirmək niyyəti ('CreateOrder', 'CapturePayment'). İnvariantları yoxlayır.
Sorğu (Query): məlumatların alınması ('GetOrderById', 'ListUserTransactions'). Yan təsirləri yoxdur.
Qeyd modeli: aqreqatlar/invariantlar/əməliyyatlar; saxlama - relyasion/açar dəyəri/hadisə log.
Oxu modeli (proyeksiyalar): materiallaşdırılmış cədvəllər/indekslər/keş, sinxronlaşdırılmış asinxron.
Uyğunluq: tez-tez qeyd və oxu arasında eventual; kritik yollar - write modelindən birbaşa oxu vasitəsilə.
Memarlıq (skelet)
1. Write xidməti: komandaları qəbul edir, invariantları təsdiqləyir, dəyişiklikləri qeyd edir (DB və ya hadisələr).
2. Outbox/CDC: dəyişiklik faktının zəmanətli nəşri.
3. proyeksiya prosessorları: hadisələr/CDC dinləmək və read-modelləri yeniləmək.
4. Read-service: materiallaşdırılmış performans/caches/axtarış queries xidmət edir.
5. Dastanlar/orkestr: kross-aqreqat proseslərini əlaqələndirir.
6. Müşahidə: lag proyeksiyaları, uğurlu tətbiqlərin faizi, DLQ.
Qeyd modelinin dizaynı
Aqreqatlar: əməliyyatların dəqiq sərhədləri (məsələn, 'Order', 'Payment', 'UserBalance').
İnvariantlar: rəsmiləşdirin (pul məbləği ≥ 0, unikallıq, limitlər).
Komandalar açar baxımından idempotentdir (məsələn, 'idempotency _ key').
Tranzaksiyalar əhatə baxımından minimaldır; xarici yan təsirləri - outbox vasitəsilə.
Komanda nümunəsi (psevdo-JSON)
json
{
"command": "CapturePayment",
"payment_id": "pay_123",
"amount": 1000,
"currency": "EUR",
"idempotency_key": "k-789",
"trace_id": "t-abc"
}
Oxu modelinin dizaynı
Sorğulardan başlayın: hansı ekranlara/hesabatlara ehtiyacınız var?
Denormalizasiyaya icazə verilir: read-model - «optimallaşdırılmış cache».
Müxtəlif tapşırıqlar üçün bir neçə proyeksiya: axtarış (OpenSearch), hesabatlar (sütun saxlama), kartlar (KV/Redis).
TTL və yenidən montaj: proyeksiyalar mənbədən bərpa edə bilməlidir (hadisə replica/snapshot).
Uyğunluq və UX
Eventual consistency: interfeys qısa zamanda köhnə məlumatları göstərə bilər.
UX nümunələri: «məlumatlar yenilənir»..., optimist UI, sinxronizasiya göstəriciləri, təsdiqlənmədən əvvəl təhlükəli hərəkətlərin bloklanması.
Güclü uyğunluq tələb edən əməliyyatlar üçün (məsələn, silinməzdən əvvəl dəqiq balansın göstərilməsi) birbaşa write modelindən oxuyun.
CQRS və Event Sourcing (isteğe bağlı)
Event Sourcing (ES) hadisələri saxlayır, aqreqatın vəziyyəti isə onların yığılmasının nəticəsidir.
CQRS + ES paketi mükəmməl audit və proyeksiyaların asan yenidən yığılmasını təmin edir, lakin mürəkkəbliyi artırır.
Alternativ: adi OLTP-DB + outbox/CDC → proyeksiya.
Replikasiya: Outbox və CDC
Outbox (bir əməliyyat): Domain dəyişikliklər qeyd + outbox hadisə qeyd; publisher təkər çatdırır.
CDC: DB log (Debezium və s.) → domen hadisələrinə çevrilmə.
Zəmanət: default at-least-once, istehlakçılar və proyeksiyalar idempotent olmalıdır.
Anbar seçimi
Write: əməliyyatlar üçün relyasion (PostgreSQL/MySQL); KV/Document - invariantların sadə olduğu yerlərdə.
Read:- KV/Redis - kartlar və sürətli açar oxunuşları;
- Axtarış (OpenSearch/Elasticsearch) - axtarış/filtrələr/fasetlər;
- Sütunlu (ClickHouse/BigQuery) - hesabatlar;
- CDN önbelləyi - ictimai kataloqlar/məzmun.
İnteqrasiya nümunələri
API təbəqəsi: «commands» və «queries» üçün ayrı-ayrı endpointlər/xidmətlər.
İdempotentlik: başlıq/bədəndə əməliyyat açarı; TTL ilə recent-keys saxlamaq.
Saqi/orkestr: zaman-autlar, kompensasiyalar, addımların təkrarlanması.
Backpressure: proyeksiya prosessorlarının paralelliyinin məhdudlaşdırılması.
Müşahidə
write metrikası: p95/99 latentlik əmrləri, uğurlu əməliyyatların payı, validasiya səhvləri.
Ölçülər: p95/99 sorğular, hit-rate cache, axtarış klasterinə yük.
Lag proyeksiyaları (vaxt və mesajlar), DLQ dərəcəsi, deduplikasiya faizi.
Trace: 'trace _ id' → outbox → proyeksiya → query komandasından keçir.
Təhlükəsizlik və uyğunluq
Hüquqların ayrılması: yazmaq və oxumaq üçün müxtəlif scopes/rollar; ən kiçik imtiyazlar prinsipi.
PII/PCI: proyeksiyalarda minimum; at-rest/in-flight şifrələmə; maskalama.
Audit: komanda, aktyor, nəticə, 'trace _ id' qeyd edin; Kritik domenlər üçün WORM arxivləri (ödənişlər, KYC).
Test
Contract tests: komandalar (səhvlər, invariantlar) və queries (formatlar/filtrlər) üçün.
Projection tests: Hadisə/CDC seriyasını təqdim edin və son oxu modelini yoxlayın.
Chaos/latency: proyeksiya prosessorlarına gecikmələrin injeksiyası; UX yoxlama lag.
Replayability: snapshot/log-dan stenddə proyeksiyaların yenidən yığılması.
Miqrasiya və təkamül
Yeni sahələr - hadisədə additiv/CDC; read-modellər yenidən yığılır.
Sxemlərin yenidən dizaynında ikiqat qeyd (dual-write); köhnə proyeksiyalar keçid qədər saxlamaq.
Version: 'v1 '/' v2' hadisə və end-point, Sunset planı.
Feature flags: Kanaryada yeni queries/proyeksiyaların daxil edilməsi.
Antipatternlər
CQRS sadə CRUD xidmətlərində «moda naminə».
Sərt sinxron oxu yazıya asılılığı (izolyasiya və sabitliyi öldürür).
Hamısı üçün bir indeks: bir read-store-da müxtəlif sorğuları qarışdırın.
Proyeksiyalarda idempotentlik yoxdur → dubllar və uyğunsuzluqlar.
Bərpa olunmayan proyeksiyalar (replay/snapshot yoxdur).
Domen nümunələri
Ödənişlər (onlayn xidmət)
Write: «Authorize», «Capture», «Refund» əməliyyat DB-də; outbox 'payment.'.
Read:- Redis «ödəniş kartı» UI üçün;
- Hesabatlar üçün ClickHouse;
- Əməliyyat axtarışı üçün OpenSearch.
- Kritik yol: avtorizasiya ≤ 800 ms p95; UI üçün oxu uyğunluğu - eventual (2-3 saniyəyə qədər).
KYC
Write: start/update status komandaları; PII qorunan DB-də saxlanılır.
Read: PII olmadan status yüngül proyeksiya; PII lazım olduqda nöqtə ilə qaldırılır.
Təhlükəsizlik: müxtəlif scopes status oxumaq və sənədlərə giriş.
Balans (iGaming/Maliyyə)
Write: 'UserBalance' atomar artımlarla/dekrementlərlə; əməliyyat üçün idempotent açarları.
Read: «sürətli balans» üçün cache; yazmaq üçün - write-dən birbaşa oxumaq (ciddi uyğunluq).
Saga: depozitlər/nəticələr hadisələrlə əlaqələndirilir, uğursuzluqlar zamanı - kompensasiyalar.
Giriş çek siyahısı
- Write modelinin aqreqatları və invariantları vurğulanır.
- Əsas queries müəyyən və onlar üçün layihələndirilmiş proyeksiyalar.
- Outbox/CDC və idempotent proyeksiya prosessorları.
- proyeksiya yenidən bir plan var (snapshot/replay).
- SLO: komandaların gizliliyi, lag proyeksiyaları, ayrı-ayrılıqda read/write mövcudluğu.
- Paylaşılan giriş hüquqları və şifrələmə həyata keçirilir.
- DLQ/lag/deuplikasiya uğursuzluqları.
- Testlər: müqavilələr, proyeksiyalar, xaos, replay.
FAQ
CQRS üçün Event Sourcing lazımdır?
Yox. Adi DB + outbox/CDC üzərində qurmaq olar.
Rassinxronizasiya ilə necə mübarizə aparmaq olar?
Açıq UX layihələndirmək, proyeksiyaların gecikməsini ölçmək, kritik əməliyyatları write-dən oxumağa vermək.
Bir xidmətdə həm write, həm də oxu saxlamaq olarmı?
Bəli, fiziki bölünmə - isteğe bağlıdır; məsuliyyətin məntiqi bölünməsi tələb olunur.
Aqreqatlar arasında əməliyyatlar haqqında nə demək olar?
Dastanlar və hadisələr vasitəsilə; mümkünsə paylanmış əməliyyatlardan çəkinin.
Yekun
CQRS əllərini açır: dəqiq invariantlarla incə, etibarlı yazma yolu və materiallaşdırılmış proyeksiyalardan sürətli, məqsədli oxunmalar. Bu, performansı artırır, təkamülü asanlaşdırır və sistemi yüklərə qarşı daha davamlı edir - uyğunluq, müşahidə və miqrasiyaları nizam-intizamla idarə edirsə.