Modelleri ve Projeksiyonları Okuyun
Read Model, belirli bir ürün senaryosu için hızlı okumalar için özel olarak tasarlanmış bir tablo/dizin/görünümdür. Projeksiyon, kaynak olayları/değişiklikleri Okuma Modeli güncellemelerine (genellikle idempotent uppert) dönüştüren bir işlemdir. CQRS ile birlikte, bu, OLTP çekirdeğini boşaltmanıza ve p95/p99 okumalarını stabilize etmenize ve "tazeliği" kontrol etmenize olanak tanır.
Ana fikirler:- Talep altında denormalize edin, "evrensel bir şema'değil.
- Aşamalı ve idempotently güncelleyin.
- Staleness ve düzeni açıkça yönetin.
1) Okuma Modelleri ne zaman kullanılır (ve ne zaman kullanılmaz)
Sığdır:- Kabul edilebilir güncelleme gecikmesiyle sık sık ağır okumalar (birleştirme/toplama/sıralama).
- Panolar, kataloglar, açılış sayfaları, "üst-N", kişisel yayınlar, arama listeleri.
- Yük paylaşımı: yazma çekirdeği - sıkı, okuma düzlemi - hızlı ve ölçeklenebilir.
- "Giriş başına" katı değişmez gerektiren işlemler (para, benzersizlik). Güçlü bir yol var.
2) Mimari taslak (sözlü şema)
1. Değişikliklerin kaynağı: OLTP'den etki alanının olayları (olay kaynağı) veya CDC.
2. Projeksiyon boru hattı: ayrıştırıcı> toplama/denormalizasyon - idempotent uppert.
3. Mağaza Oku: Sorgu için optimize edilmiş veritabanı/dizin (RDBMS, sütun, arama).
4. API/client: "as_of/freshness" nitelikleriyle hızlı SELECT/GET.
3) Model tasarımını okuyun
Bir sorgu ile başlayın: hangi alanlar, filtreler, sıralama, sayfalama, üst N?
Denormalize: Zaten birleştirilmiş verileri (adlar, miktarlar, durumlar) depolar.
- Bölümleme: 'tenant _ id', tarih, bölgeye göre.
- Birincil anahtar: iş anahtarı + zaman kovası (örneğin, '(tenant_id, entity_id)' veya '(tenant_id, bucket_minute)').
- Dizinler: Sıklığa göre nerede/siparişe göre.
- TTL/retention: geçici vitrinler için (örn. 90 gün).
4) Akış ve idempotensi güncelleyin
Idempotent uppert, projeksiyon stabilitesinin temelidir.
Sözde: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);
Kurallar:
- Her mesaj bir sürüm/saat taşır; Sadece "taze veya eşit" (idempotency) kabul edin.
- Toplamlar için (sayaçlar, toplamlar) - durumu saklayın ve değişmeli güncellemeleri (veya CRDT yaklaşımlarını) kullanın.
5) Değişimin Kaynağı: Olaylar vs CDC
Olaylar (olay kaynağı): zengin semantik, farklı projeksiyonlar oluşturmak kolaydır; Devrelerin evrimi önemlidir.
CDC (mantıksal çoğaltma): basitçe mevcut bir veritabanına bağlanın; DML - sobyty haritalama ve gürültü güncelleme filtreleme gerekli olacaktır.
- Teslimat garantileri (en az bir kez) ve "zehirli" mesajlar için DLQ.
- Anahtarla sipariş (bölüm anahtarı = 'tenant _ id: entity _ id').
6) Düzen, nedensellik ve "tazelik"
Anahtarla sipariş: bir nesnenin olayları sırayla gelmelidir; Bölümleme ve sürümleri kullanın.
Oturum/nedensel: Yazarın değişikliklerini (RYW) görmesi için, sorgularda filigran sürümlerini iletin.
Sınırlı staleness: Return'as _ of'/' X-Data-Freshness've SLO tutun (örn. P95 ≤ 60c).
7) Artımlı agregalar ve üst N
Dakika satış kovaları örneği: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;
Üst N için:
- Sıralı bir vitrini koruyun (örneğin, 'gelir DESC'ile) ve yalnızca değişen pozisyonları güncelleyin (yığın/skiplist/sınırlı tablo).
- Üst kısmın "penceresini" saklayın (örneğin, segment başına 100-1000 satır).
8) Arama ve coğrafi projeksiyon
Arama (ES/Opensearch): denormalize belge, boru hattı dönüşümleri, belge sürümü = kaynak sürüm.
Geo: 'POINT/LAT, LON', ön agrega karoları/dörtlüleri saklayın.
9) Çok kiracı ve bölgeler
Projeksiyon anahtarları ve olaylarında 'tenant _ id' gereklidir.
Adalet: Kiracı başına projeksiyonların verimliliğini sınırlayın (WFQ/DRR), böylece "gürültülü" geri kalanı yavaşlatmaz.
İkamet: projeksiyon, yazma çekirdeği ile aynı bölgede yaşar; Bölgelerarası vitrinler - kümeler/özetler.
10) Gözlemlenebilirlik ve SLO
Metrikler:- 'prosection _ lag _ ms' (istochnik ^ vitrina), 'tazelik _ age _ ms' (son deltadan beri).
- Güncellemelerin çıktısı, hata oranı, DLQ oranı, redrive başarısı.
- Pencere boyutu, p95/p99 okuma gecikmesi.
- Теги: 'tenant _ id', 'entity _ id', 'event _ id', 'version', 'projection _ name', 'trial'.
- Ek açıklamalar: birleştirme çözümleri, eski sürümlerin ihmal edilmesi.
11) Playbook'lar (runbook'lar)
1. Gecikme büyümesi: konektörü/aracıyı kontrol edin, partileri artırın, önemli vitrinlerin önceliklendirilmesini ekleyin.
2. Birçok şema hatası: redrive'ı dondurun, şemaları geçirin (geri doldurun), eşleyicinin yeni bir sürümüyle yeniden başlatın.
3. Tekrarlanan DLQ: toplu işlemi azaltın, "gölge" işleyicisini etkinleştirin, idempotensi artırın.
4. Pencere tutarsızlığı: Pencereleri pencere başına günlük/kaynaktan yeniden oluşturun (kiracı/bölüm seçimi).
5. Kısayol tuşları: rekabeti anahtarla sınırlayın, yerel kuyruklar ekleyin, birimi ayrı bir vitrine koyun.
12) Tam yeniden sayım (yeniden oluşturma) ve geri doldurma
Yaklaşım:- Tüketimi durdurun (veya vitrinin yeni bir sürümüne geçin).
- Gruplar halinde yeniden hesaplayın (toplu/tarih/kiracı ile).
- İki fazlı anahtarı etkinleştir: önce 'read __ v2'yi doldurun, ardından atomik olarak okuma yönlendirmesini değiştirin.
13) Devrelerin evrimi (sürüm oluşturma)
'schema _ version'in olaylar/belgeler.
Projeksiyon birkaç versiyonu okuyabilir, anında geçiş yapabilir.
Büyük değişiklikler için - yeni bir v2 vitrini ve kanarya trafiği.
14) Güvenlik ve erişim
Kaynaktan RLS/ACL miras; Vitrini erişimde orijinal verilerden daha geniş yapmayın.
UX/analitik için gerekli olmayan projeksiyonlarda PII'yi maskeleyin.
Redrives/recounts/manüel düzenlemelerin denetimi.
15) Yapılandırma şablonu
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 hatalar
"Tüm durumlar için bir vitrin" - ağır güncellemeler ve kötü p99.
Idempotency eksikliği - agregalarda kopyalar/atlar.
Doğrudan vitrine çift yazma ve OLTP - tutarsızlıklar.
Tazeliğin sıfır görünürlüğü - ürünle ilgili çelişkili beklentiler.
İki fazlı bir anahtar olmadan yeniden oluşturun - cevaplarda "delikler".
Bölümleme/indeks yok - maliyet ve gecikme artışı.
17) Hızlı tarifler
Katalog/arama: belge vitrini + artımlı upsert, lag ≤ 5-15 s, filtreler için dizinler.
Panolar: dakika/saat tankları, 'SUM/COUNT' üniteleri, p95 tazelik ≤ 60 sn.
Kişisel bant: yazar için kullanıcı + nedensel/RYW tarafından projeksiyon, önbelleğe geri dönüş.
Global SaaS: bölgesel vitrinler, bölgeler arası agregalar; kiracı başına adalet.
18) Satış öncesi kontrol listesi
- Vitrin belirli bir istek için tasarlanmıştır; endeksler ve partiler var.
- Seçilen değişimin kaynağı (olaylar/CDC); Teslimat garantileri ve anahtar siparişi.
- versiyonları/zaman ile Idempotent upsert; "Eski" olaylara karşı koruma.
- Tazelik SLO tanımlanır ve cevaplanır ('as _ of/tazelik ').
- DLQ ve Secure Release yapılandırılmış; Yeniden inşa/dolgu üzerine oyun kitabı.
- Anahtar başına seri ve kiracı başına adalet.
- Gecikme/hata/gecikme metrikleri, p95/p99 uyarıları ve DLQ büyümesi.
- Devre sürüm ve geçiş stratejisi (v2 + anahtar).
- Erişim/PII politikaları miras alınır ve doğrulanır.
Sonuç
Modeller ve projeksiyonlar, okumaların bir mühendislik hızlandırıcısıdır: tahmin edilebilir milisaniyeler elde etmek ve kayıtların çekirdeğini boşaltmak için "tazelik've akış altyapısı için küçük bir fiyat ödersiniz. İsteğinize uygun vitrinler tasarlayın, güncellemeleri idempotent yapın, gecikmeyi ölçün ve açıkça tazelik vaat edin - ve API'leriniz artan yük, veri ve coğrafya ile bile hızlı kalacaktır.