CQRS жана окуу/жазуу бөлүштүрүү
CQRS деген эмне
CQRS (Command Query Responsibility Segregation) - жазуу (commands) жана окуу (queries) үчүн жооптуу маалыматтардын моделин жана компоненттерин бөлгөн архитектуралык ыкма.
Идея: абалды өзгөртүү процесси валиддик инварианттар жана транзакциялар үчүн оптималдаштырылат, ал эми окуу тез, максаттуу проекциялар жана масштабдоо үчүн оптималдаштырылат.
Эмне үчүн бул керек
Окуу өндүрүмдүүлүгү: конкреттүү сценарийлер (тасмалар, отчеттор, каталогдор) боюнча материалдык проекциялар.
Критикалык жолдун туруктуулугу: Жазуу "оор" джоиндерден жана агрегаттардан обочолонгон.
сактоо тандоо эркиндиги: жазуу үчүн OLTP, окуу үчүн OLAP/кэш/издөө кыймылдаткычтары.
Тездетилген эволюция: бүтүмдөрдү "сындыруу" коркунучу жок жаңы идеяларды кошуу.
Байкоо жана аудит (өзгөчө Event Sourcing менен бирге): калыбына келтирүү жана абалын сабап, жеңил.
Качан колдонуу керек (жана качан эмес)
ылайыктуу, эгерде:- Ар кандай маалымат тилкелери жана татаал агрегациясы менен окуулар басымдуулук кылат.
- Критикалык жазуу жолу жука жана алдын ала болушу керек.
- Окуу жана жазуу үчүн ар кандай SLO/SLA керек.
- Аналитикалык/издөө муктаждыктарынан жазуунун домендик логикасын изоляциялоо талап кылынат.
- Домен жөнөкөй, жүк төмөн; CRUD аткарат.
- Окуу менен жазуунун ортосундагы күчтүү ырааттуулук бардык сценарийлер үчүн милдеттүү.
- Команда тажрыйбасыз, ал эми операциялык татаалдыгы кабыл алынгыс.
Негизги түшүнүктөр
Команда (Command): абалын өзгөртүү ниети ('CreateOrder', 'CapturePayment'). Инварианттарды текшерет.
Суроо-талап (Query): маалыматтарды алуу ('GetOrderById', 'ListUserTransactions'). эч кандай терс таасирлери.
Жазуу модели: агрегаттар/инварианттар/транзакциялар; сактоо - реляциялык/ачкыч мааниси/окуя журналы.
Окуу модели (проекциялар): материалдаштырылган таблицалар/индекстер/кэш, синхрондуу эмес.
ырааттуулук: көп учурда жазуу жана окуу ортосунда eventual; критикалык жолдор - write моделинен түз окуу аркылуу.
Архитектура
1. Write-кызматы: буйруктарды кабыл алат, өзгөрүүлөрдү тастыктайт, өзгөрүүлөрдү белгилейт (DD же окуялар).
2. Outbox/CDC: өзгөрүүлөр чындыкты жарыялоо кепилденген.
3. Проекция процессорлору: окуяларды/CDC угуу жана окуу моделдерин жаңыртуу.
4. Read-кызматы: материалдык идеялар/кэш/издөө queries кызмат кылат.
5. Сагалар/оркестрлер: кросс-агрегаттык процесстерди координациялайт.
6. Байкоо: проекция артта, ийгиликтүү колдонуу пайызы, DLQ.
Жазуу моделин долбоорлоо
Агрегаттар: транзакциялардын так чектери (мисалы, 'Order', 'Payment', 'UserBalance').
Инварианттар: формалдаштыруу (накталай суммалар ≥ 0, уникалдуулук, лимиттер).
Командалар ачкыч боюнча демпотенттик (мисалы, 'idempotency _ key').
Транзакциялар камтылышы боюнча минималдуу; тышкы терс таасирлери - outbox аркылуу.
Команданын үлгүсү (псевдо-JSON)
json
{
"command": "CapturePayment",
"payment_id": "pay_123",
"amount": 1000,
"currency": "EUR",
"idempotency_key": "k-789",
"trace_id": "t-abc"
}
Окуу моделин долбоорлоо
Суроо-талаптардан баштап: кандай экрандар/отчеттор керек?
Денормализация жол берилет: read-модель - "оптималдаштырылган кэш".
Ар кандай тапшырмалар үчүн бир нече проекциялар: издөө (OpenSearch), отчеттор (колонка сактоо), карталар (KV/Redis).
TTL жана кайра чогултуу: проекцияларды булактан калыбына келтире билүү керек (окуялардын репликасы/снапшот).
Ырааттуулук жана UX
Eventual consistency: interface кыска мөөнөттүү эски маалыматтарды көрсөтө алат.
UX үлгүлөрү: "маалыматтар жаңыланып жатат"..., оптимисттик UI, синхрондоштуруу көрсөткүчтөрү, тастыкталганга чейин кооптуу иш-аракеттерди бөгөттөө.
Катуу ырааттуулукту талап кылган операциялар үчүн (мисалы, эсептен чыгаруунун алдында так балансты көрсөтүү) түздөн-түз write моделинен окуңуз.
CQRS жана Event Sourcing (каалагандай)
Event Sourcing (ES) окуяларды сактайт, ал эми агрегаттын абалы алардын жыйындысынын натыйжасы болуп саналат.
CQRS + ES тобу идеалдуу аудит жана проекцияларды жеңил кайра чогултуу берет, бирок татаалдыгын жогорулатат.
Альтернатива: кадимки OLTP-DD + outbox/CDC → проекция.
Replication: Outbox жана CDC
Outbox (бир бүтүмүндө): домендик өзгөрүүлөрдү жазуу + outbox окуяларды жазуу; коомдук шинага жеткирет.
CDC: DD логунан окуу (Debezium ж.б.) → домендик окуяларга трансформация.
Кепилдиктер: демейки ат-least-once, керектөөчүлөр жана проекциялар idempotent болушу керек.
Кампаларды тандоо
Write: транзакциялар үчүн реляциялык (PostgreSQL/MySQL); KV/Document - бул жерде инварианттар жөнөкөй.
Read:- KV/Redis - карталар жана тез ачкыч окуу;
- Издөө (OpenSearch/Elasticsearch) - издөө/чыпкалар/фасеттер;
- Колонна (ClickHouse/BigQuery) - отчеттор;
- CDN кэш - коомдук каталогдор/мазмун.
Интеграция үлгүлөрү
API катмары: Өзүнчө End Points/Services үчүн 'commands' жана 'queries'.
Idempotentity: аталышы/дене иш ачкычы; TTL менен recent-keys сактоо.
Сагалар/оркестр: тайм-ауттар, компенсациялар, кадамдардын кайталанышы.
Backpressure: проекция процессорлорунун параллелизмин чектөө.
Байкоо
write Metrics: p95/99 жашыруун команда, ийгиликтүү бүтүмдөрдүн үлүшү, validation каталар.
Метрика окуп: p95/99 суроолор, hit-rate кэш, издөө кластерге жүктөө.
Проекциялардын артта калышы (убакыт жана билдирүүлөр), DLQ ставкасы, дедупликациялардын пайызы.
Trace: 'trace _ id' командасы аркылуу өтөт → outbox → проекция → query.
Коопсуздук жана комплаенс
Укуктарды бөлүштүрүү: жазуу жана окуу үчүн ар кандай scopes/ролдору; эң аз артыкчылыктардын принциби.
PII/PCI: проекцияларды минималдаштыруу; at-rest/in-flight шифрлөө; маскировка.
Аудит: команда, актер, натыйжасы, 'trace _ id'; маанилүү домендер үчүн WORM-Archives (төлөмдөр, KYC).
Тестирлөө
Contract tests: командалар үчүн (каталар, инварианттар) жана queries (форматтар/чыпкалар).
Projection tests: окуялар/CDC сериясын берүү жана акыркы окуу моделин текшерүү.
Chaos/latency: проекция процессорлоруна кечигүү инжекциясы; лагада UX текшерүү.
Replayability: Snapshot/Logo стендде проекцияларды кайра чогултуу.
Миграция жана эволюция
Жаңы талаалар - аддитивдүү окуя/CDC; Read-моделдер кайра чогултулат.
Кош жазуу (dual-write) редизайн схемалар менен; эски проекцияларды которулганга чейин сактайбыз.
Версиялоо: 'v1 '/' v2' окуялар жана эндпоинттер, Sunset-план.
Feature flags: канарейка боюнча жаңы queries/проекцияларды киргизүү.
Антипаттерндер
CQRS жөнөкөй CRUD кызматтарында "мода үчүн".
Катуу синхрондуу окуу жазууга көз карандылыгы (изоляцияны жана туруктуулукту өлтүрөт).
Бардыгы үчүн бир индекс: бир окуу дүкөнүндө ар түрдүү суроо-талаптарды аралаштыруу.
проекцияларда идемпотенттүүлүк жок → дубль жана айырмачылыктар.
Калыбына келбеген проекциялар (реплика/снапшот жок).
Домендик мисалдар
Төлөмдөр (онлайн сервис)
Write: 'Authorize', 'Capture', 'Refund' транзакциялык DD; outbox 'payment.' жарыялайт.
Read:- Redis UI үчүн "төлөм карточкасы";
- отчеттор үчүн ClickHouse;
- Транзакцияларды издөө үчүн OpenSearch.
- Критикалык жол: авторизация ≤ 800 ms p95; UI үчүн окуу ырааттуулугу - eventual (2-3 с чейин).
KYC
Write: баштоо/жаңылоо статусу боюнча командалар; PII коопсуз DD сактоо.
Read: PII жок статустардын жеңил проекциясы; PII керек болсо чекитке тартылат.
Коопсуздук: ар кандай scopes статусун окуу жана документтерге жетүү.
Баланстар (iGaming/каржы)
Write: 'UserBalance' атомдук инкременттер/декременттер менен бирдиги; операция үчүн демпотенттик ачкычтар.
Read: "тез баланс" үчүн кэш; эсептен чыгаруу үчүн - түздөн-түз окуу (катуу ырааттуулук).
Сага: депозиттер/корутундулар окуялар менен координацияланат, мүчүлүштүктөр болгон учурда - компенсация.
Киргизүүнүн чек-тизмеси
- Write моделдин агрегаттары жана инварианттары бөлүнгөн.
- Негизги queries аныкталган жана алар үчүн проекциялар иштелип чыккан.
- Outbox/CDC жана Idempotent проекция процессорлору.
- Проекцияларды кайра чогултуу планы бар (snapshot/replay).
- SLO: жашыруун командалар, артта проекцияларды, өзүнчө read/write жеткиликтүүлүгү.
- Кирүү укуктары жана маалыматтарды шифрлөө бөлүштүрүлдү.
- DLQ/лаг/дедупликация ийгиликсиз.
- Тесттер: келишимдер, проекциялар, башаламандык, реплика.
FAQ
CQRS үчүн Event Sourcing керек?
Жок. Кадимки DD + outbox/CDC курууга болот.
Расинхронизация менен кантип күрөшүү керек?
Так UX долбоорлоо, проекцияларды өлчөө, критикалык операцияларга окуу үчүн write.
Бир кызматта write да, окуу да сактоого болобу?
Ооба, физикалык бөлүштүрүү - кошумча; жоопкерчиликтин логикалык бөлүнүшү милдеттүү.
Агрегаттардын ортосундагы транзакциялар жөнүндө эмне айтууга болот?
дастандар жана окуялар аркылуу; эгер мүмкүн болсо, бөлүштүрүлгөн транзакциялардан качыңыз.
Жыйынтык
CQRS колун бошотот: так өзгөрүүсүз жана тез, материалдык проекциялардан максаттуу окуу менен кылдат, ишенимдүү жазуу жолу. Бул өндүрүмдүүлүктү жогорулатат, эволюцияны жөнөкөйлөтөт жана системаны жүктөргө туруктуураак кылат - эгерде ырааттуулук, байкоо жана миграция тартиптүү башкарылса.