GH GambleHub

Czytaj modele i projekcje

Czytaj Model jest specjalnie zaprojektowaną tabelą/indeksem/widokiem dla szybkich odczytów dla konkretnego scenariusza produktu. Projekcja to proces konwertujący zdarzenia źródłowe/zmiany do aktualizacji Read Model (zwykle idempotent upsert). W połączeniu z CQRS pozwala to rozładować rdzeń OLTP i ustabilizować odczyty p95/p99, kontrolując „świeżość”.

Główne pomysły:
  • Denormalizować na żądanie, a nie „uniwersalny schemat”.
  • Aktualizuj stopniowo i idempotentnie.
  • Wyraźnie zarządzaj stalością i porządkiem.

1) Kiedy używać modeli odczytu (a kiedy nie)

Pasuje do:
  • Częste odczyty ciężkie (połączenia/agregacje/rodzaje) z dopuszczalnym opóźnieniem aktualizacji.
  • Deski rozdzielcze, katalogi, strony lądowania, „top-N”, kanały osobiste, listy wyszukiwań.
  • Współdzielenie obciążenia: rdzeń zapisu - ścisły, czytelny - szybki i skalowalny.
Nie nadaje się:
  • Operacje wymagające ścisłych stałych „na wejście” (pieniądze, wyjątkowość). Jest silna droga.

2) Zarys architektoniczny (schemat słowny)

1. Źródło zmian: zdarzenia domeny (event sourcing) lub CDC z OLTP.
2. Rurociąg projekcyjny: parser → agregacja/denormalizacja → idempotent upsert.
3. Przeczytaj sklep: baza danych/indeks zoptymalizowany dla zapytania (RDBMS, kolumna, wyszukiwanie).
4. API/client: quick SELECT/GET, z atrybutami „as_of/freshness”.

3) Przeczytaj wzór

Zacznij od zapytania: które pola, filtry, sortowanie, paginacja, top N?
Denormalizuj: Przechowywać już połączone dane (nazwy, kwoty, statusy).

Klucze:
  • Podział: przez 'lokator _ id', data, region.
  • Klucz podstawowy: klucz biznesowy + wiadro czasowe (na przykład „(tenant_id, entity_id)” lub „(tenant_id, bucket_minute)”).
  • Indeksy: przez częste miejsce/zamówienie przez.
  • TTL/retencja: dla czasowych przypadków wyświetlania (np. 90 dni).

4) Aktualizacja przepływu i idempotencji

Idempotent upsert jest podstawą stabilności projekcji.

Pseudo:
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);
Zasady:
  • Każda wiadomość zawiera wersję/godzinę; akceptować tylko „świeże lub równe” (idempotencja).
  • Dla agregatów (liczniki, sumy) - przechowywać stan i używać aktualizacji commutative (lub podejścia CRDT).

5) Źródło zmian: Wydarzenia vs CDC

Wydarzenia (event sourcing): bogata semantyka, łatwo jest zbudować różne projekcje; ewolucja obwodów jest ważna.
CDC (replikacja logiczna): wystarczy połączyć się z istniejącą bazą danych; DML → wymagane będzie mapowanie sobyty i filtrowanie aktualizacji szumów.

Obie opcje wymagają:
  • Gwarancje dostawy (przynajmniej raz) i DLQ dla „trujących” wiadomości.
  • Kolejność według klucza (klucz partycji = 'lokator _ id: entity _ id').

6) Porządek, przyczynowość i „świeżość”

Kolejność według klucza: zdarzenia jednego obiektu muszą przychodzić kolejno; używać partycji i wersji.
Sesja/przyczyna: Aby autor mógł zobaczyć ich zmiany (RYW), podaj wersje znaków wodnych w zapytaniach.
Ograniczona stalowość: powrót' as _ of "/" X-Data-Freshness "i trzymać SLO (np. p95 ≤ 60c).

7) Kruszywa przyrostowe i górne N

Przykład minutowych wiader sprzedaży:
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;
Dla Top N:
  • Utrzymuj ranking prezentacji (na przykład przez 'revenue DESC') i aktualizuj tylko zmienione pozycje (hałas/skiplist/ograniczona tabela).
  • Przechowywać „okno” góry (na przykład 100-1000 linii na segment).

8) Wyszukiwanie i geo-projekcja

Wyszukiwanie (ES/Opensearch): znormalizowany dokument, przekształcenia rurociągu, wersja dokumentu = wersja źródłowa.
Geo: sklep „POINT/LAT, LON”, płytki/quady wstępnie zagregowane.

9) Wieloosobowy najemca i regiony

'lokator _ id' jest wymagany w kluczykach projekcyjnych i zdarzeniach.
Uczciwość: ograniczyć przepustowość rzutów na najemcę (WFQ/DRR), aby „hałas” nie spowalniał reszty.
Rezydencja: projekcja mieszka w tym samym regionie co rdzeń pisma; międzyregionalne prezentacje - agregaty/podsumowania.

10) Obserwowalność i SLO

Metryka:
  • „projection _ lag _ ms” (istochnik → vitrina), „freshness _ age _ ms” (od ostatniej delty).
  • przepustowość aktualizacji, szybkość błędów, szybkość DLQ, redrive-sukces.
  • Rozmiar okna, opóźnienie odczytu p95/p99.
Śledzenie/dzienniki:
  • Тера: 'tenant _ id',' entity _ id', 'event _ id',' version ',' projection _ name ',' attempt '.
  • Adnotacje: rozwiązania scalające, pominięcie przestarzałych wersji.

11) Playbooks (książki startowe)

1. Opóźnienie wzrostu: sprawdź złącze/broker, zwiększyć partie, zawierać priorytety kluczowych prezentacji.
2. Wiele błędów schematu: zamrożenie redrive, migracja schematów (backfill), ponowne uruchomienie z nową wersją mapera.
3. Powtarzane DLQ: zmniejszyć partię, włączyć obsługę „cieni”, zwiększyć idempotencję.
4. Niespójność okna: odbudować okna z dziennika/źródła na okno (lokator/partycja selektywna).
5. Hot keys: ograniczyć konkurencję o klucz, dodać lokalne kolejki, umieścić jednostkę w osobnej prezentacji.

12) Pełne przeliczenie (odbudowa) i zasypka

Podejście:
  • Zatrzymaj zużycie (lub przełącz na nową wersję prezentacji).
  • Przeliczyć w partiach (według partii/daty/najemcy).
  • Włącz przełącznik dwufazowy: najpierw wypełnić 'read __ v2', a następnie atomowo przełączyć odczytaną trasę.

13) Ewolucja obwodów (wersioning)

„schema _ version” w wydarzeniach/dokumentach.
Projekcja może odczytać kilka wersji, migrację na muchę.
Dla dużych zmian - nowa prezentacja v2 i ruch kanaryjski.

14) Bezpieczeństwo i dostęp

Dziedzicz RLS/ACL ze źródła; nie czynią prezentacji szerszym w dostępie niż oryginalne dane.
Maska PII w projekcjach niepotrzebnych do UX/analityki.
Audyt rededycji/recount/edycji ręcznych.

15) Szablon konfiguracji

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) Typowe błędy

„Jeden pokaz dla wszystkich przypadków” → ciężkie aktualizacje i zły p99.
Brak idempotencji → duplikaty/skoki w kruszywach.
Dual-write bezpośrednio do prezentacji i OLTP → rozbieżności.
Zero widoczności świeżości → sprzeczne oczekiwania z produktem.
Odbudować bez przełącznika dwufazowego → „dziury” w odpowiedziach.
Brak podziału/indeksów → wzrost kosztów i opóźnień.

17) Szybkie przepisy kulinarne

Katalog/wyszukiwanie: prezentacja dokumentów + przyrostowy upsert, lag ≤ 5-15 s, indeksy dla filtrów.
Deski rozdzielcze: zbiorniki minutowe/godzinne, jednostki "SUM/COUNT', świeżość p95 ≤ 60 s.
Taśma osobista: projekcja przez użytkownika + przyczynowy/RYW dla autora, wpadka do pamięci podręcznej.
Globalny system SaaS: regionalne prezentacje, agregaty międzyregionalne; uczciwość na najemcę.

18) Lista kontrolna przedsprzedaży

  • Prezentacja jest przeznaczona do konkretnego wniosku; są indeksy i partie.
  • Wybrane źródło zmian (zdarzenia/CDC); gwarancje dostawy i kluczowe zamówienie.
  • Idempotent upsert z wersjami/czas; ochrona przed „starymi” wydarzeniami.
  • Świeżość SLO jest zdefiniowana i odpowiadana („as _ of/freshness”).
  • Skonfigurowane DLQ i Secure Release; playbook on rebuild/backfill.
  • Na klucz seryjny i uczciwość na najemcę.
  • Wskaźniki lag/error/latency, alerty p95/p99 i wzrost DLQ.
  • Strategia weryfikacji obwodów i migracji (v2 + switch).
  • Polityki dostępu/PII są dziedziczone i zatwierdzone.

Wnioski

Czytaj Modele i projekcje są inżynierskim akceleratorem odczytów: płacisz niewielką cenę za „świeżość” i infrastrukturę strumieniową, aby uzyskać przewidywalne milisekundy i odciążyć rdzeń nagrań. Projektowanie sklepów, aby dostosować się do Twojej prośby, uczynić aktualizacje idempotentne, zmierzyć opóźnienie i wyraźnie obiecać świeżość - a Twoje interfejsy API pozostaną szybkie nawet przy rosnącym obciążeniu, danych i geografii.

Contact

Skontaktuj się z nami

Napisz do nas w każdej sprawie — pytania, wsparcie, konsultacje.Zawsze jesteśmy gotowi pomóc!

Rozpocznij integrację

Email jest wymagany. Telegram lub WhatsApp są opcjonalne.

Twoje imię opcjonalne
Email opcjonalne
Temat opcjonalne
Wiadomość opcjonalne
Telegram opcjonalne
@
Jeśli podasz Telegram — odpowiemy także tam, oprócz emaila.
WhatsApp opcjonalne
Format: kod kraju i numer (np. +48XXXXXXXXX).

Klikając przycisk, wyrażasz zgodę na przetwarzanie swoich danych.