Event Sourcing: əsasları
Event Sourcing nədir
Event Sourcing (ES) - domen obyektlərinin vəziyyətini «cari xətt» şəklində deyil, baş verən hər şeyi təsvir edən dəyişməz hadisə jurnalı kimi saxlamaq üsuludur. Aqreqatın hazırkı vəziyyəti onun hadisələrinin bükülməsi (replay) ilə əldə edilir və hər hansı bir oxu ideyası bu jurnalın üstündəki proyeksiyalar kimi qurulur.
Əsas nəticələr:- Tarix - «həqiqətin ilkin mənbəyi», dövlət - tarixin proyeksiyasıdır.
- Hər hansı bir vəziyyəti yenidən canlandırmaq, yoxlamaq və izah etmək olar (audit).
- Yeni fikirlərin və analitikaların əlavə edilməsi köhnə «şəkillərin» miqrasiyasını tələb etmir - hadisələri itirmək kifayətdir.
Əsas terminlər
Aqreqat - aydın invariantlarla (Order, Payment, UserBalance) uyğunluq domen vahidi.
Hadisə - keçmişdə baş verən dəyişməz faktdır ('payment. authorized`, `order. shipped`).
Event Store - aqreqat daxilində hadisələrin qaydasını təmin edən append-online jurnal.
Aqreqat versiyası - son tətbiq olunan hadisənin nömrəsi (optimistic concurrency üçün).
Snapshot - bükülməni sürətləndirmək üçün dövri vəziyyət.
Proyeksiya (read-model) - oxu/axtarış/hesabat üçün materiallaşdırılmış növ (çox vaxt - asenxron).
Necə işləyir (komanda axını → hadisələr → proyeksiyalar)
1. Müştəri ('CapturePayment', 'PlaceOrder') əmrini göndərir.
2. Aqreqat invariantları təsdiqləyir və hər şey qaydasındaysa, hadisələri yaradır.
3. Hadisələr Event Store-a versiya yoxlaması (optimistic concurrency) ilə atomik olaraq əlavə olunur.
4. Proyeksiya prosessorları hadisələrin axınına abunə olur və read-modelləri yeniləyir.
5. Aşağıdakı komanda üçün aqreqatı yüklədikdə vəziyyət bərpa olunur: snapshot (əgər varsa) → snapshot sonrası hadisələr.
Hadisə dizaynı
Məcburi atributlar (nüvə)
json
{
"event_id": "uuid",
"event_type": "payment. authorized. v1",
"aggregate_type": "Payment",
"aggregate_id": "pay_123",
"aggregate_version": 5,
"occurred_at": "2025-10-31T10:42:03Z",
"payload": { "amount": 1000, "currency": "EUR", "method": "card" },
"meta": { "trace_id": "t-abc", "actor": "user_42" }
}
Tövsiyələr:
- Adı: 'domain. action. v{major}`.
- Additivlik: Yeni sahələr - köhnə mənasını dəyişmədən, isteğe bağlıdır.
- Minimalizm: asanlıqla bərpa edilə bilən məlumatların təkrarlanması olmadan yalnız faktlar.
Müqavilələr və sxemlər
Sxemləri düzəldin (Avro/JSON Schema/Protobuf) və CI uyğunluğunu yoxlayın.
«Sındırıcı» dəyişikliklər üçün - hadisənin yeni əsas versiyası və miqrasiya dövrü üçün 'v1 '/' v2' paralel nəşri.
Rəqabətli giriş: optimistic concurrency
Qayda: Yeni hadisələrin yazılması yalnız 'expected _ version = = current_version' olduqda mümkündür.
Psevdokod:pseudo load: snapshot(state, version), then apply events > version new_events = aggregate. handle(command)
append_to_store(aggregate_id, expected_version=current_version, events=new_events)
//if someone has already written an event between load and append, the operation is rejected -> retray with reload
Beləliklə, biz paylanmış əməliyyatlar olmadan invariantların bütövlüyünü təmin edirik.
Snapshots (yığma sürətləndirilməsi)
Hər N hadisə və ya zamanlayıcı snapshot edin.
Храните `snapshot_state`, `aggregate_id`, `version`, `created_at`.
Snapshot sonrası hadisələri həmişə yoxlayın və tutun (yalnız qəlibə etibar etməyin).
Snapshotları yığından çıxarın («sehrli» sahələri saxlamayın).
Proyeksiyalar və CQRS
ES təbii CQRS ilə birləşir:- Write modeli = aqreqatlar + Event Store.
- Read-modellər = hadisələrlə yenilənən proyeksiyalar (Redis kartları, axtarış üçün OpenSearch, hesabatlar üçün ClickHouse/OLAP).
- Proyeksiyalar idempotentdir: eyni 'event _ id' təkrar emalı nəticəni dəyişmir.
Sxemlərin təkamülü və uyğunluğu
Additive-first: sahələr əlavə edin; növləri/semantikasını dəyişdirməyin.
Mürəkkəb dəyişikliklər üçün: yeni hadisə növlərini buraxın və projeksiyon miqratorlarını yazın.
Keçid dövründə ikiqat yazını ('v1' + 'v2') saxlayın və bütün proyeksiyalar hazır olduqda 'v1' filmini çəkin.
Təhlükəsizlik, PII və «unudulmaq hüququ»
Hekayə tez-tez həssas məlumatları ehtiva edir. Yanaşmalar:- Hadisələrdə PII-ni minimuma endirin (məlumat əvəzinə identifikatorlar, detallar - qorunan tərəflərdə).
- Kriptovalyutası: Sahələri şifrələyin və silinməsi tələb edildikdə açarı məhv edin (hadisə qalır, lakin məlumat yoxdur).
- Hadisələr-redaksiya: 'user. piiredacted. v1 'proyeksiyalarda həssas sahələrin dəyişdirilməsi ilə (tarix redaktə faktını saxlayır).
- Retence Siyasəti: Bəzi domenlər üçün bəzi hadisələr WORM anbarında arxivlənə bilər.
Performans və miqyaslandırma
Partiyalaşdırma: sıra aqreqat daxilində vacibdir - 'aggregate _ id' ilə partiyalaşdırın.
Soyuq başlanğıc: snapshots + periodik «möhürləmə» paketi.
Batch append: hadisələri bir əməliyyat ilə qruplaşdırın.
Projeksiyon prosessorları üçün Backpressure və DLQ; lag ölçün (vaxt və mesajların sayı).
Event Store indeksləşdirilməsi: '(aggregate_type, aggregate_id)' və vaxt ilə sürətli giriş.
Test
aqreqatlar üçün Specification tests: script «komandalar → gözlənilən hadisələr».
Projection tests: Hadisələrin axınını təqdim edin və materiallaşdırılmış vəziyyəti/indeksləri yoxlayın.
Replayability tests: stenddə «sıfırdan» proyeksiyaları yenidən seçin - nəticənin üst-üstə düşdüyünə əmin olun.
Chaos/latency: gecikmələri və dublları enjekte edin, idempotentliyi yoxlayın.
Domen nümunələri
1) Ödənişlər
Hadisələr: 'payment. initiated`, `payment. authorized`, `payment. captured`, `payment. refunded`.
İnvariantlar: 'authorized' olmadan 'capture' olmaz; məbləğlər mənfi deyil; valyuta dəyişməz.
Proyeksiyalar: «ödəniş kartı» (KV), əməliyyat axtarışı (OpenSearch), hesabat (OLAP).
2) Sifarişlər (e-ticarət)
Hadisələr: 'order. placed`, `order. paid`, `order. packed`, `order. shipped`, `order. delivered`.
İnvariantlar: status diaqramına görə status keçidləri; ləğv 'shipped' qədər mümkündür.
Proyeksiyalar: istifadəçi sifarişlərinin siyahısı, statuslara görə SLA-daşbordlar.
3) Balans (maliyyə/iGaming)
Hadisələr: 'balance. deposited`, `balance. debited`, `balance. credited`, `balance. adjusted`.
Sərt invariant: balans <0; komandalar idempotentdir 'operation _ id'.
Kritik əməliyyatlar birbaşa aqreqatdan (ciddi uyğunluq), UI - proyeksiyadan (eventual) oxunur.
Event Store-un standart strukturu (DB ilə seçim)
events
`event_id (PK)`, `aggregate_type`, `aggregate_id`, `version`, `occurred_at`, `event_type`, `payload`, `meta`
İndeks: '(aggregate_type, aggregate_id, version)'.
snapshots
`aggregate_type`, `aggregate_id`, `version`, `state`, `created_at`
İndeks: '(aggregate_type, aggregate_id)'.
consumers_offsets
'consumer _ id', 'event _ id '/' position', 'updated _ at' (proyeksiyalar və retlay üçün).
Tez-tez suallar (FAQ)
Hər yerdə ES istifadə etmək məcburiyyətidirmi?
Yox. ES, audit, mürəkkəb invariantlar, təkrarlanabilirlik və müxtəlif məlumat təqdimatları vacib olduqda faydalıdır. Sadə CRUD üçün bu artıq.
Bəs «aktual vəziyyət» sorğuları?
Ya proyeksiyadan oxuyun (tez, eventual), ya da aqreqatdan (daha bahalı, lakin ciddi). Kritik əməliyyatlar adətən ikinci yolu istifadə edir.
Kafka/Stream Broker lazımdır?
Event Store - həqiqət mənbəyi; broker proyektorlara və xarici sistemlərə hadisələri yaymaq üçün əlverişlidir.
«Unudulmaq hüququ» ilə nə etmək lazımdır?
PII-ni minimuma endirin, həssas sahələri şifrələyin və proyeksiyalarda kriptovalyuta/redaktə tətbiq edin.
Köhnə məlumatları necə köçürmək olar?
Hadisələrin retrospektiv nəslinin skriptini yazın («re-highstory») və ya «vəziyyət-olduğu kimi» ilə başlayın və hadisələri yalnız yeni dəyişikliklər üçün dərc edin.
Antipatternlər
Event Sourcing «vərdişlə»: domen faydası olmadan sistemi çətinləşdirir.
Fat events: PII və dubl ilə şişmiş payload - əyləc və uyğunluq problemləri.
Optimist concurrency olmaması: yarış zamanı invariant itkisi.
Bərpa olunmayan proyeksiyalar: replay/snapshot → əl fiksləri yoxdur.
Domen hadisələri kimi xam CDC: DB sxemlərinin sızması və sərt əlaqə.
Daxili və inteqrasiya hadisələrinin qarışdırılması: sabitləşdirilmiş «vitrin» dərc edin.
Production üçün çek siyahısı
- Aqreqatlar, invariantlar və hadisələr (adlar, versiyalar, sxemlər) müəyyən edilmişdir.
- Event Store vahid və optimistic concurrency daxilində nizam təmin edir.
- Snapshotlar və onların yenidən qurulması planı daxil edilmişdir.
- Projeksiyalar idempotent, DLQ və lag metrik var.
- Sxemlər CI-də təsdiqlənir, versiyalar siyasəti - sənədləşdirilir.
- PII minimuma endirilir, sahələr şifrələnir, «unudulma» strategiyası var.
- Proyeksiya replizi stenddə yoxlanılır; təcili bərpa planı var.
- Dashboard: append sürəti, lag proyeksiyaları, tətbiq səhvləri, retras payı.
Yekun
Event Sourcing sistem tarixini birinci dərəcəli bir artefakt edir: biz faktları qeyd edirik, onlardan vəziyyəti təkrarlayırıq və hər hansı bir təsəvvürü sərbəst qururuq. Bu, sxemlərdə nizam-intizam, rəqabətli nəzarət və həssas məlumatlarla bacarıqlı işləmək şərti ilə audit, dəyişikliklərə davamlılıq və analitikanın çevikliyini təmin edir.