Read Models va proyeksiyalar
Read Model - bu ma’lum bir mahsulot stsenariysida tez o’qish uchun maxsus ishlab chiqilgan jadval/indeks/tur. Proyeksiya - hodisa/manbadagi oʻzgarishlarni Read Model yangilanishiga (odatda idempotent upsert) aylantiradigan jarayon. CQRS bilan birgalikda bu OLTP yadrosini tushirish va p95/p99 o’qishni barqarorlashtirish imkonini beradi.
Asosiy g’oyalar:- «Universal sxema» emas, balki so’rov asosida denormallashtirish.
- Inkremental va idempotent tarzda yangilash.
- Staleness va tartibni aniq boshqarish.
1) Qachon ishlatish uchun Read Models (va qachon ishlatmaslik)
Mos keladi:- Tez-tez ogʻir oʻqish (joinlar/agregatsiyalar/saralash) va yangilanish kechikishi.
- Dashbordlar, kataloglar, lendinglar, «top-N», shaxsiy faydlar, qidiruv ro’yxatlari.
- Yuk taqsimoti: write-yadro - qattiq, read-tekislik - tezkor va masshtabli.
- «Har bir yozuv uchun» qat’iy invariantlarni talab qiladigan operatsiyalar (pul, noyoblik). U yerda - strong path.
2) Arxitektura konturi (so’z sxemasi)
1. Oʻzgarishlar manbai: OLTP dan domen voqealari (event sourcing) yoki CDC.
2. Proyeksiya konveyeri: parser → aggregatsiya/denormalizatsiya → idempotent upsert.
3. Read Store: So’rov uchun optimallashtirilgan DB/indeks (RDBMS, kolonochnыe, qidiruv).
4. API/mijoz: tezkor SELECT/GET, «as_of/freshness» atributlari bilan.
3) Read Model loyihalashtirish
So’rov bilan boshlang: qaysi sohalar, filtrlar, saralash, paginatsiya, top-N?
Denormallashtiring: allaqachon birlashtirilgan maʼlumotlarni (nomlar, summalar, maqomlar) saqlang.
- Partiyalashtirish:’tenant _ id’, sana, mintaqa.
- Primary key: biznes-kalit + vaqtinchalik baket (masalan,’(tenant_id, entity_id)’yoki’(tenant_id, bucket_minute)’).
- Indekslar: tez-tez where/order by.
- TTL/retenshn: vaqtinchalik vitrinalar uchun (masalan, 90 kun).
4) Yangilanishlar oqimi va idempotentlik
Idempotent upsert - proyeksiyalar barqarorligining asosi.
Psevdo:sql
-- Projection table
CREATE TABLE read_orders (
tenant_id TEXT,
order_id UUID,
status TEXT,
total NUMERIC(12,2),
customer JSONB,
updated_at TIMESTAMP,
PRIMARY KEY (tenant_id, order_id)
);
-- Idempotent update by event
INSERT INTO read_orders(tenant_id, order_id, status, total, customer, updated_at)
VALUES (:tenant,:id,:status,:total,:customer,:ts)
ON CONFLICT (tenant_id, order_id) DO UPDATE
SET status = EXCLUDED. status,
total = EXCLUDED. total,
customer = COALESCE(EXCLUDED. customer, read_orders. customer),
updated_at = GREATEST(EXCLUDED. updated_at, read_orders. updated_at);
Qoidalar:
- Har bir xabar versiyani/vaqtni olib boradi; faqat «yangi yoki teng» (idempotency) ni qabul qilamiz.
- Agregatlar uchun (hisoblagichlar, summalar) - state saqlang va kommutativ yangilanishlardan (yoki CRDT yondashuvlaridan) foydalaning.
5) Oʻzgarishlar manbai: hodisalar vs CDC
Voqealar (event sourcing): boy semantika, turli proyeksiyalarni qurish oson; sxemalar evolyutsiyasi muhim ahamiyatga ega.
CDC (mantiqiy replikatsiya): faqat mavjud DBga ulash; DML → hodisalar mappingini va shovqin yangiliklarini filtrlashni talab qiladi.
- «Zaharli» xabarlar uchun yetkazib berish kafolatlari (at-least-once) va DLQ.
- Kalit tartibi (partition key =’tenant _ id: entity _ id’).
6) Tartib, sabablar va «yangilik»
Kalit bo’yicha tartib: bitta obyektning voqealari ketma-ket kelishi kerak; partiyalashtirish va versiyalardan foydalaning.
Sababi (session/causal): muallif oʻzining oʻzgarishlarini (RYW) koʻrishi uchun, soʻrovlardagi watermark versiyasini uzating.
Yangilik (bounded staleness):’as _ of ’/’ X-Data-Freshness’ni qaytaring va SLOni saqlang (masalan, p95 ≤ 60 c).
7) Inkremental agregatlar va top-N
Bir daqiqalik savdo baketalari misoli:sql
CREATE TABLE read_sales_minute (
tenant_id TEXT,
bucket TIMESTAMP, -- toStartOfMinute revenue NUMERIC(14,2),
orders INT,
PRIMARY KEY (tenant_id, bucket)
);
-- Update by Event
INSERT INTO read_sales_minute(tenant_id, bucket, revenue, orders)
VALUES (:tenant,:bucket,:amount, 1)
ON CONFLICT (tenant_id, bucket) DO UPDATE
SET revenue = read_sales_minute. revenue + EXCLUDED. revenue,
orders = read_sales_minute. orders + 1;
Top-N uchun:
- Rangli vitrinani (masalan,’revenue DESC’) qoʻllab-quvvatlang va faqat oʻzgargan pozitsiyalarni (heap/skiplist/limited table) yangilang.
- Yuqori «oynani» saqlang (masalan, segmentga 100-1000 satr).
8) Qidiruv va geo-proyeksiyalar
Qidirish (ES/Opensearch): denormallashtirilgan hujjat, pipeline transformatsiyalar, hujjat versiyasi = manba versiyasi.
Geo:’POINT/LAT, LON’ni saqlang.
9) Multi-tenant va hududlar
’tenant _ id’ proyeksiyalar va hodisalar kalitlarida majburiy.
Fairness: «shovqin» boshqalarni sekinlashtirmasligi uchun per tenant (WFQ/DRR) proyeksiyalarini cheklang.
Residency: proyeksiya write-yadro bilan bir mintaqada yashaydi; mintaqalararo vitrinalar - agregatlar/ma’lumotlar.
10) Kuzatuv va SLO
Metriklar:- ’projection _ lag _ ms’ (manba → vitrin),’freshness _ age _ ms’(oxirgi deltadan boshlab).
- yangilanishlar, xatolar ulushi, DLQ-rate, redrive-success.
- Vitrin oʻlchami, p95/p99 latentlik oʻqish.
- Теги: `tenant_id`, `entity_id`, `event_id`, `version`, `projection_name`, `attempt`.
- Izohlar: merge-echimlar, eskirgan versiyalarni oʻtkazib yuborish.
11) Pleybuklar (runbooks)
1. Lag’ning o’sishi: konnektor/brokerni tekshirish, partiyalarni ko’paytirish, asosiy vitrinalarni ustuvorlashtirishni kiritish.
2. Sxemada koʻplab xatolar mavjud: tahrirlarni muzlatish, sxemalarni koʻchirish (backfill), mapperning yangi versiyasi bilan qayta ishga tushirish.
3. Takroriy DLQ: batchni kamaytirish, «soyali» ishlov beruvchini yoqish, idempotentlikni kuchaytirish.
4. Vitrinaning nomuvofiqligi: jurnal/manbadan deraza orqasiga rebuild vitrinani bajarish (tenant/partition bo’yicha tanlash).
5. Issiq kalitlar: kalit bo’yicha raqobatni cheklash, lokal navbatlar qo’shish, agregatni alohida vitrinaga olib chiqish.
12) To’liq qayta hisoblash (rebuild) va backfill
Yondashuv:- Isteʼmolni toʻxtatish (yoki vitrinaning yangi versiyasiga oʻtish).
- Paket sifatida qayta hisoblash (partiya/sana/tenant bo’yicha).
- Ikki fazali svitchni yoqing: avval’read __ v2’ni to’ldiring, so’ngra o’qish yo’nalishini atomik ravishda o’zgartiring.
13) Sxemalar evolyutsiyasi (versiyalash)
Hodisa/hujjatlarda’schema _ version’.
Proyeksiya bir nechta versiyalarni o’qishga qodir, migratsiya «uchish».
Katta o’zgarishlar uchun - yangi vitrin v2 va kanar trafigi.
14) Xavfsizlik va foydalanish
Manbadan RLS/ACLni meros qilib oling; vitrinani dastlabki ma’lumotlarga qaraganda kengroq qilmang.
UX/analitik uchun zarur boʻlmagan proyeksiyalarda PIIni yashiring.
Tahrirlash/qayta hisoblash/qo’lda tuzatishlar auditi.
15) Konfiguratsiya namunasi
yaml projections:
read_orders:
source: kafka. orders. events partition_key: "{tenant_id}:{order_id}"
idempotency: version_ts upsert:
table: read_orders conflict_keys: [tenant_id, order_id]
freshness_slo_ms: 60000 dlq:
topic: orders. events. dlq redrive:
batch: 500 rate_limit_per_sec: 50 read_sales_minute:
source: cdc. orders partition_key: "{tenant_id}:{bucket_minute}"
aggregate: increment retention_days: 90 limits:
per_tenant_parallelism: 4 per_key_serial: true observability:
metrics: [projection_lag_ms, dlq_rate, redrive_success, read_p95_ms]
16) Tipik xatolar
«Barcha holatlar uchun bitta vitrin» → og’ir yangilanishlar va yomon p99.
Agregatlarda idempotentlik yo’qligi → dubli/sakrash.
Dual-write to’g’ridan-to’g’ri vitrinaga va OLTP → tafovutlar.
Yangi ko’rinish yo’q → mahsulot bilan kutish to’qnashuvi.
Rebuild ikki fazali svitchsiz → javoblarda «teshiklar».
Partiyalash/indekslar yo’q → qiymat va latentlik o’sishi.
17) Tezkor retseptlar
Katalog/qidiruv: hujjatli vitrin + inkremental upsert, lag ≤ 5-15 c, filtrlar uchun indekslar.
Dashbordlar: daqiqali/soatlik baketalar, agregatlar «SUM/COUNT», p95 yangilik ≤ 60 s.
Shaxsiy lenta: muallif uchun + causal/RYW proyeksiyasi, keshga fallback.
Global SaaS: mintaqaviy vitrinalar, kross-mintaqaviy agregatlar; fairness per tenant.
18) Sotishdan oldingi chek-varaq
- Vitrin aniq so’rov asosida loyihalashtirilgan; indekslar va partiyalar mavjud.
- Oʻzgarishlar manbai tanlangan (hodisalar/CDC); yetkazib berish kafolatlari va kalit bo’yicha tartib.
- Versiyali/vaqtli idempotent upsert; «eski» voqealardan himoya qilish.
- SLO yangiligi aniqlandi va javoblarda beriladi (’as _ of/freshness’).
- DLQ va xavfsiz redrayv sozlangan; pleybuk rebuild/backfill.
- Raqobatni cheklash (per-key serial) va fairness per tenant.
- Lag/xato/latency metrikasi, p95/p99 uchun alertlar va DLQ o’sishi.
- Sxemalarni versiyalash va migratsiya strategiyasi (v2 + svitch).
- Kirish/PII siyosati meros qilib olingan va tekshirilgan.
Xulosa
Read Models va proyeksiyalar - bu o’qishni tezlashtiruvchi muhandislik: siz bashorat qilinadigan millisekundlarni olish va yozuv yadrosini tushirish uchun ozgina «yangilik» va striming infratuzilmasi uchun pul to’laysiz. So’rov uchun vitrinalarni loyihalashtiring, yangilanishlarni idempotent qiling, lag o’lchang va aniq yangilik va’da qiling - va sizning APIlaringiz yuk, ma’lumotlar va geografiya ko’paygan taqdirda ham tez bo’lib qoladi.