ღონისძიება Sourcing: საფუძვლები
რა არის Event Sourcing
Event Sourcing (ES) არის დომენის ობიექტების მდგომარეობის შენახვის მეთოდი არა „მიმდინარე ხაზის“ სახით, არამედ როგორც მოვლენების უცვლელი ჟურნალი, რომელიც აღწერს ყველაფერს, რაც მოხდა. აგრეგატის ამჟამინდელი მდგომარეობა მიიღება მისი მოვლენების შეფუთვით, ხოლო კითხვის ნებისმიერი წარმოდგენა აგებულია, როგორც პროექცია ამ ჟურნალის თავზე.
ძირითადი გამოძიებები:- ისტორია არის „ჭეშმარიტების პირველადი წყარო“, მდგომარეობა არის ისტორიის პროექცია.
- ნებისმიერი მდგომარეობის ხელახლა რეპროდუცირება, შემოწმება და ახსნა (აუდიტი).
- ახალი წარმოდგენებისა და ანალიტიკოსების დამატება არ საჭიროებს ძველი „სურათების“ მიგრაციას - საკმარისია მოვლენების დაკარგვა.
ძირითადი ტერმინები
დანაყოფი არის თანმიმდევრული დომენის ერთეული მკაფიო ინვარიანტებით (Order, Payment, UserBalance).
ღონისძიება არის უცვლელი ფაქტი, რომელიც მოხდა წარსულში ('payment. authorized`, `order. shipped`).
Event Store არის Append-only ჟურნალი, რომელიც უზრუნველყოფს ღონისძიების წესრიგს განყოფილებაში.
დანაყოფის ვერსია არის ბოლო გამოყენებული მოვლენის ნომერი (ოპტიკური კონკურენციისთვის).
Snapshot არის პერიოდული სახელმწიფო black, რათა დააჩქაროს პაკეტი.
პროექცია (read მოდელი) არის მატერიალიზებული სახეობა კითხვისა/ძიების/ანგარიშგების (ხშირად ასინქრონული).
როგორ მუშაობს ეს (გუნდების ნაკადი მოვლენებისა და პროექციებისთვის)
1. კლიენტი აგზავნის გუნდს ('CapturePayment', 'PlaceOrder').
2. აგრეგატი წარმართავს ინვარიანტებს და, თუ ყველაფერი კარგია, ქმნის მოვლენებს.
3. მოვლენები ატომურად ემატება Event Store- ს ვერსიის შემოწმებით (optimistic concurrence).
4. პროექციის პროცესორები გაფორმებულია მოვლენების ნაკადზე და განახლდება read მოდელები.
5. შემდეგი გუნდისთვის დანაყოფის დატვირთვისას, მდგომარეობა აღდგება: snapshot (თუ არსებობს) - მოვლენები snapshot- ის შემდეგ.
მოვლენების დიზაინი
სავალდებულო ატრიბუტები (ბირთვი)
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" }
}
რეკომენდაციები:
- სახელწოდება: 'domain. action. v{major}`.
- დანამატი: ახალი ველები არჩევითია, ძველების მნიშვნელობის შეცვლის გარეშე.
- მინიმალიზმი: მხოლოდ ფაქტები, ადვილად აღდგენილი მონაცემების დუბლირების გარეშე.
კონტრაქტები და სქემები
შეამოწმეთ სქემები (Avro/JSON Schema/Protobuf) და შეამოწმეთ თავსებადობა CI- ზე.
„გატეხილი“ ცვლილებებისთვის - ღონისძიების ახალი მთავარი ვერსია და მიგრაციის პერიოდის 'v1 '/' v2' პარალელური გამოქვეყნება.
კონკურენტული წვდომა: optimistic concurrence
წესი: ახალი მოვლენების ჩაწერა შესაძლებელია მხოლოდ იმ შემთხვევაში, თუ 'expected _ version = = current _ version'.
ფსევდო კოდი: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
ასე რომ, ჩვენ გარანტიას ვაძლევთ ინვალიდთა მთლიანობას განაწილებული გარიგების გარეშე.
Snaphots (პაკეტის აჩქარება)
გააკეთეთ snapshot ყოველ N მოვლენაში ან ტაიმერში.
Храните `snapshot_state`, `aggregate_id`, `version`, `created_at`.
ყოველთვის შეამოწმეთ და დაიჭირეთ მოვლენები სნაიპშოტის შემდეგ (ნუ ენდობით მხოლოდ ბრეკეტს).
ამოიღეთ სლაიდები ისე, რომ მათი ამოღება შესაძლებელია ლოგიდან (არ შეინახოთ „ჯადოსნური“ ველები).
პროექცია და CQRS
ES ბუნებრივად ერწყმის CQRS:- Write მოდელი = დანაყოფები + Event Store.
- Read მოდელები = მოვლენების განახლებული პროგნოზები (Redis ბარათები, OpenSearch საძიებო, ClickHouse/OLAP ანგარიშებისთვის).
- პროექციები idempotenty: იგივე 'event _ id' განმეორებითი დამუშავება არ ცვლის შედეგს.
სქემების ევოლუცია და თავსებადობა
Additive-first: დაამატეთ ველები; ნუ შეცვლით ტიპებს/სემანტიკას.
რთული ცვლილებებისთვის: გამოუშვეთ ახალი ტიპის მოვლენები და დაწერეთ პროექციის მიგრატორები.
შეინარჩუნეთ ორმაგი ჩანაწერი ('v1' + 'v2') გარდამავალი პერიოდისთვის და ამოიღეთ 'v1 ", როდესაც ყველა პროექცია მზად არის.
უსაფრთხოება, PII და „დავიწყების უფლება“
ისტორია ხშირად შეიცავს მგრძნობიარე მონაცემებს. მიდგომები:- მინიმუმამდე დაიყვანეთ PII ღონისძიებებში (იდენტიფიკატორები მონაცემების ნაცვლად, დეტალები დაცულ მხარეებში).
- კრიპტო-წაშლა: დაშიფვრის ველები და, როდესაც ითხოვს წაშლას, გაანადგურეთ გასაღები (ღონისძიება რჩება, მაგრამ მონაცემები მიუწვდომელია).
- სარედაქციო ღონისძიებები: 'user. piiredacted. v1 'მგრძნობიარე ველების ჩანაცვლებით პროექციებში (ისტორია ინარჩუნებს რედაქტირების ფაქტს).
- გამოკითხვის პოლიტიკა: ზოგიერთი დომენისთვის, მოვლენების ნაწილი შეიძლება დაარქივდეს WORM საცავებში.
შესრულება და სკალირება
განაწილება: ბრძანება მნიშვნელოვანია დანაყოფის შიგნით - პარტიზანული _ id '.
ცივი სტარტი: Snaphots + პერიოდული „cupping“ პაკეტი.
Batch დანართი: დაჯგუფეთ მოვლენები ერთი გარიგებით.
Backpressure და DLQ პროექციის პროცესორებისთვის; გაზომეთ ლაგი (შეტყობინებების დრო და რაოდენობა).
Event Store- ის ინდექსაცია: სწრაფი წვდომა '(gregate _ ტიპი, gregate _ id)' და დროულად.
ტესტირება
სპეციალობის ტესტები აგრეგატებისთვის: სცენარი „გუნდი - მოსალოდნელი მოვლენები“.
Projection tests: წარუდგინეთ მოვლენების ნაკადი და შეამოწმეთ მატერიალური მდგომარეობა/ინდექსები.
გამოსწორება: გადააკეთეთ პროექცია „ნულიდან“ სტენდზე - დარწმუნდით, რომ შედეგი ემთხვევა.
Chaos/latency: შეინარჩუნეთ შეფერხებები და დუბლები, შეამოწმეთ idempotence.
დომენების მაგალითები
1) გადახდა
მოვლენები: 'payment. initiated`, `payment. authorized`, `payment. captured`, `payment. refunded`.
ინვარიანტები: შეუძლებელია 'capture' '' authorized 'გარეშე; თანხები უარყოფითია; ვალუტა უცვლელია.
პროგნოზები: „გადახდის ბარათი“ (KV), გარიგების ძებნა (OpenSearch), ანგარიშები (OLAP).
2) შეკვეთები (ელექტრონული კომერცია)
მოვლენები: 'წესრიგი. placed`, `order. paid`, `order. packed`, `order. shipped`, `order. delivered`.
ინვარიანტები: სტატუსის გადასვლები სახელმწიფო დიაგრამის მიხედვით; გაუქმება შესაძლებელია 'shipped'.
პროგნოზები: მომხმარებლის შეკვეთების სია, SLA დაშბორდები სტატუსებისთვის.
3) ბალანსები (ფინანსები/iGaming)
მოვლენები: 'balance. deposited`, `balance. debited`, `balance. credited`, `balance. adjusted`.
მკაცრი ინვარიანტი: ბალანსი არ მიდის <0; ბრძანებები არის idempotent 'operation _ id'.
კრიტიკული ოპერაციები იკითხება უშუალოდ განყოფილებიდან (მკაცრი კოორდინაცია), UI - პროექციიდან (წინასწარ).
Event Store- ის ტიპიური სტრუქტურა (ვარიანტი BD- ით)
events
`event_id (PK)`, `aggregate_type`, `aggregate_id`, `version`, `occurred_at`, `event_type`, `payload`, `meta`
ინდექსი: '(agregate _ type, aggregate _ id, ვერსია)'.
snapshots
`aggregate_type`, `aggregate_id`, `version`, `state`, `created_at`
ინდექსი: '(gregate _ type, aggregate _ id)'.
consumers_offsets
'consumer _ id', 'event _ id '/' position', 'განახლება _ at' (პროექციებისა და რეტლეებისთვის).
ხშირი კითხვები (FAQ)
ნამდვილად გამოიყენეთ ES ყველგან?
არა. ES სასარგებლოა, როდესაც მნიშვნელოვანია აუდიტი, რთული ინვარიანტები, რეპროდუქცია და მონაცემთა სხვადასხვა წარმოდგენა. მარტივი CRUD- სთვის ეს ზედმეტია.
რა შეიძლება ითქვას „ამჟამინდელი მდგომარეობის“ მოთხოვნებზე?
ან წაიკითხეთ პროექციიდან (სწრაფად, საღამოს), ან აგრეგატიდან (უფრო ძვირი, მაგრამ მკაცრად). კრიტიკული ოპერაციები, როგორც წესი, მეორე გზას იყენებს.
გჭირდებათ Kafka/stream ბროკერი?
Event Store - ჭეშმარიტების წყარო; ბროკერი მოსახერხებელია პროექტორებისა და გარე სისტემების განაწილებისთვის.
რა უნდა გავაკეთოთ „დავიწყების უფლებით“?
მინიმუმამდე დაიყვანეთ PII, დაშიფვრა მგრძნობიარე ველები და გამოიყენეთ კრიპტო-წაშლა/გამოცემა პროექციებში.
როგორ გადავიტანოთ ძველი მონაცემები?
დაწერეთ მოვლენების რეტროსპექტული თაობის სკრიპტი („re-history“) ან დაიწყეთ „სახელმწიფო-როგორ“ და გამოაქვეყნეთ მოვლენები მხოლოდ ახალი ცვლილებებისთვის.
ანტიპატერები
ღონისძიება Sourcing „ჩვევის მიხედვით“: ართულებს სისტემას დომენის გარეშე.
Fat events: გაბერილი payload's ერთად PII და დუბლები - მუხრუჭები და შესაბამისობის პრობლემები.
optimistic currence- ის არარსებობა: რბოლაში ინვარიანტების დაკარგვა.
არაპროგნოზირებადი პროგნოზები: არ არსებობს რეპლიკა/სნაიპშოტები, სახელმძღვანელო ფიქსაცია.
ნედლეული CDC, როგორც აფეთქების ღუმელის მოვლენები: BD სქემების გაჟონვა და მკაცრი კავშირი.
შიდა და ინტეგრაციის მოვლენების შერევა: გამოაქვეყნეთ სტაბილიზებული „ფანჯარა“.
ჩეკის სია წარმოებისთვის
- განისაზღვრება დანაყოფები, ინვარიანტები და მოვლენები (სახელები, ვერსიები, სქემები).
- Event Store უზრუნველყოფს წესრიგს დანაყოფისა და ოპტიკური კონსულტაციის ფარგლებში.
- ჩართულია სლაიდები და მათი ხელახლა შექმნის გეგმა.
- პროექციები idempotente, არის DLQ და lage მეტრიკა.
- სქემები ვალიდდება CI- ზე, ვერსიის პოლიტიკა დოკუმენტირებულია.
- PII მინიმუმამდეა დაყვანილი, ველები დაშიფრულია, არსებობს სტრატეგია „დავიწყება“.
- პროგნოზების რეპლიკა შემოწმებულია სტენდზე; არსებობს გადაუდებელი აღდგენის გეგმა.
- დაშბორდი: მადის სიჩქარე, პროექციის ლაქები, გამოყენების შეცდომები, რეტრატების წილი.
შედეგი
Event Sourcing სისტემის ისტორიას პირველი კლასის არტეფაქტად აქცევს: ჩვენ ვაწარმოებთ ფაქტებს, მათგან ვრეპროდუცირებთ მდგომარეობას და თავისუფლად ვქმნით ნებისმიერ სპექტაკლს. ეს იძლევა აუდიტს, ცვლილებებისადმი წინააღმდეგობას და ანალიტიკის მოქნილობას - ექვემდებარება სქემებში დისციპლინას, კონკურენტულ კონტროლს და მგრძნობიარე მონაცემებთან კომპეტენტურ მუშაობას.