GH GambleHub

Outbox შაბლონი

Outbox არის არქიტექტურული ნიმუში, რომელშიც აფეთქების ღუმელის სერვისი წერს ბიზნეს ცვლილებას და შესაბამის მოვლენას ერთ ადგილობრივ გარიგებაში, მის საცავში. ღონისძიების გამოქვეყნება გარე საბურავზე/რიგში ხორციელდება ასინქრონულად ცალკეული უსაფრთხო პროცესით (publisher), კითხულობს outbox ცხრილს და სარელეო ჩანაწერებს. ეს მიდგომა გამორიცხავს რბოლას „ჯერ BD- ში, შემდეგ საბურავზე“ და უზრუნველყოფს საიმედო მიწოდებას, თუნდაც წარუმატებლობის შემთხვევაში.

1) გამოყენებისას

შესაფერისია:
  • მიკროსერვისი და მოდულური მონოლითები კონტექსტებს შორის მოვლენებით.
  • აუცილებელია გარანტია, რომ „მდგომარეობა დაფიქსირდა. მოვლენა არ შეიძლება დაიკარგოს“.
  • ჩვენ გვჭირდება idempotence და კონტროლირებადი განმეორებითი მიწოდება.
არ არის შესაფერისი:
  • კრიტიკულად მკაცრი გლობალური გარიგებები რამდენიმე რესურსზე (უკეთესია TSS/საგა აშკარა კონტრაქტებით).
  • არ არსებობს ჭეშმარიტების განსაკუთრებული წყარო (სახელმწიფო ინახება არა იქ, სადაც მოვლენა წარმოიქმნება).

2) მიზნები და თვისებები

Atomic write: დომენის ჩაწერა + outbox - ერთ გარიგებაში.
At-least-once პუბლიკაცია: ჩვენ ვუშვებთ განმეორებას, აღმოფხვრის ზარალს.
მომხმარებელთა იდემპოტენტურობა: აბონენტების მხარეს დუბლებისგან დაცვა.
ეფექტური exactly-once: მიიღწევა გარე + idempotent consumer + dedup- ის კომბინაციით.
მკაფიო ტელემეტრია: ბიზნეს ოპერაციებისა და მოვლენების კორელაცია.

3) მონაცემთა სქემა (მაგალითი)

sql
-- Domain table (example: orders)
CREATE TABLE orders (
id       UUID PRIMARY KEY,
tenant_id    TEXT NOT NULL,
status     TEXT NOT NULL,
total_amount  NUMERIC(12,2) NOT NULL,
updated_at   TIMESTAMP NOT NULL DEFAULT now()
);

-- Outbox
CREATE TABLE outbox (
id       UUID PRIMARY KEY,        -- event_id aggregate_type TEXT NOT NULL,          -- 'order'
aggregate_id  UUID NOT NULL,          -- order_id tenant_id    TEXT NOT NULL,
type      TEXT NOT NULL,          -- 'OrderCreated'
payload JSONB NOT NULL, -- serialized headers event JSONB NOT NULL DEFAULT '{}':: jsonb,
occurred_at TIMESTAMP NOT NULL, -- time in domain transaction available_at TIMESTAMP NOT NULL, -- earliest publish time (backoff)
published_at TIMESTAMP, - is filled by the attempts INT NOT NULL DEFAULT 0,
error      TEXT
);

CREATE INDEX ON outbox (available_at) WHERE published_at IS NULL;
CREATE INDEX ON outbox (tenant_id, available_at) WHERE published_at IS NULL;

4) გარიგების შაბლონი

pseudo begin tx domainChange () # INSERT/UPDATE in domain table insert into outbox (event) # event with aggregate/tenant commit tx keys

თუ კომუნა წარმატებულია, გარედან მოვლენა გარანტირებულია. თუ აპლიკაცია დაეცემა კომიტის შემდეგ, პაბლიცერი დაიჭერს.

5) პაბლიშერი

დავალებები:
  • პერიოდულად წაიკითხეთ გამოუქვეყნებელი მოვლენები ('published _ at IS NULL' და 'available _ at <= now ()'), ბრძოლები.
  • შეეცადეთ გამოაქვეყნოთ საბურავი/ხაზი; წარმატების მისაღწევად - აღნიშნეთ 'published _ at'.
  • შეცდომით - გაზარდეთ 'attempts', დააყენეთ 'available _ at' მომავლისთვის (ექსპონენტური ბაჩოფი), დაწერეთ 'error'.
  • პატივისცემა ტენიანობის/კლავიშების შესახებ, არ დაბლოკოს.
ფსევდო კოდი:
pseudo loop:
events = select from outbox where published_at is null and available_at <= now()
order by occurred_at limit BATCH_SIZE for update skip locked

for e in events:
try:
broker. publish(topicFor(e), serialize(e. payload), headers(e))
markPublished(e. id, now())
except Retryable:
backoff = computeBackoff(e. attempts)
reschedule(e. id, now()+backoff, attempts+1, last_error)
except NonRetryable:
moveToDLQ (e) or markError (e) # by sleep (POLL_INTERVAL) policy
💡 „განახლებისთვის SKIP LOCKED“ გამორიცხავს საზოგადოების კონკურენციას.

6) Idempotence და deduplication

მომხმარებლის მხარეს (Inbox/Idempotence Store):
sql
CREATE TABLE inbox (
consumer_name  TEXT,
event_id    UUID,
processed_at  TIMESTAMP NOT NULL,
PRIMARY KEY (consumer_name, event_id)
);

ალგორითმი: ღონისძიების მიღებისას - პირველი მცდელობა 'INSERT' inbox '; თუ საკვანძო კონფლიქტი - მოვლენა უკვე დამუშავებულია „არა-op“. შემდეგი არის ბიზნეს ლოგიკა.

პაბლიცერის მხარეს: 'Idempotency-Key' headers (მაგალითად, 'event _ id') ისე, რომ საბურავები/ბროკერი/მარიონეტული შეიძლება გაფილტრული იყოს დუბლიკატებით.

7) წესრიგი და მიზეზი

ადგილობრივი ბრძანება 'agregate _ id' უზრუნველყოფილია 'occurred _ at' დახარისხებით და „გასაღების“ გამოქვეყნებით.
განაწილების მქონე ლოგის საბურავებისთვის - დააკოპირეთ 'aggregate _ id '/' tenant _ id' გასაღები ისე, რომ ერთი განყოფილების მოვლენები ერთ ნაწილად იყოს.
თუ შეკვეთა კრიტიკულია, თავიდან აიცილეთ საზოგადოების რბოლა ერთი გასაღებით.

8) CDC (Change Data Capture)

აქტიური საზოგადოების ნაცვლად, შეგიძლიათ გამოიყენოთ CDC: ძრავა კითხულობს BD გარიგების ჟურნალს და „outbox“ ხაზებს გადასცემს საბურავზე. უპირატესობები - მინიმალური დატვირთვა BD- ზე, ზუსტი თანმიმდევრობა, ნახევარგამოყოფის არარსებობა. უარყოფითი მხარეა ოპერაციის გართულება და DBMS- ის სპეციფიკის დაკავშირება. ორივე მიდგომა რეალურია; შეარჩიეთ კომპეტენციები და SLO.

9) შეცდომები, DLQ და რადარი

Retryable (ქსელი, ლიმიტები) - ჩვენ ვზრდით 'attempts- ს', გადადით 'available _ at' (exponential backoff + gitter).
Non-retryable (შეუქცევადი სქემა/კონტრაქტი) - ჩვენ გადავცემთ DLQ/Dead-Letter Topic- ს მდიდარი მეტამონაცემებით.
უსაფრთხო redrive: batch, rate-limit, სქემის შესაბამისობა, პრიორიტეტი პროდ-ტრაფიკის ქვემოთ.

10) მულტფილმები და ლიმიტები

სავალდებულო ჭდეები: 'tenant _ id', 'plan', 'region' - outbox- ში. headers`.
Per-tenant fairness: საზოგადოება ანაწილებს პუბლიკაციების „ფანჯრებს“ და იჯარის მცდელობების შეზღუდვებს.
Residence: შეინახეთ გარე ბოქსი იმავე რეგიონში, სადაც დომენის მონაცემები; რეგიონალური პუბლიკაცია - მხოლოდ დანაყოფები/მოხსენებები.

11) უსაფრთხოება და შესაბამისობა

PII გამოცემა payload/headers ტენანტის/რეგიონის პოლიტიკის შესახებ.
დატვირთვის ხელმოწერა/დაშიფვრა, თუ საბურავი „უცხოა“.
სახელმწიფო ყველა გადასვლის აუდიტი: შეიქმნა, გამოქვეყნდა შეცდომა, რედრივი.

12) დაკვირვება

მეტრიკა:
  • პუბლიკაციის lag ('now - occurred _ at' p50/p95/p99).
  • წარმატების წილი, შეცდომების წილი, მიზეზების განაწილება.
  • Outbox- ის ზომა (გამოუქვეყნებელი), მცდელობები/წმ.
  • throughput და lag per- ჩრდილოვანი გრაფიკები.
ვაჭრობა:
  • 'event _ id '/' aggregate _ id '/' saga _ id' კორელაცია; სპანი „db-tx“, „publish“, „retry“.
  • მენიუ: 'attempt', 'backoff _ ms', 'dlq = ნამდვილი'.
ლოგიკა:
  • მოკლე წარმატების ჩანაწერები; შეცდომის/რედაქციის სრული დეტალები.

13) ტესტირება და ქაოსი

ატომიური ტესტი: ხელოვნურად „დაეცემა“ აფეთქების ღუმელის გარიგების შემდეგ, გამოქვეყნებამდე - ღონისძიება მოგვიანებით უნდა გამოვიდეს.
Duplicate ტესტი: ჩვენ რამდენჯერმე ვაქვეყნებთ ერთსა და იმავე მოვლენას - კონსიმერი ზუსტად ერთ ეფექტს ასრულებს (inbox).
რიგის ტესტი: ერთი განყოფილების მოვლენების პაკეტი - თანმიმდევრობის/idempotent- ის შემოწმება.
ქაოსი: ბროკერის უარყოფა, BD- ს ლატენტობის ზრდა, split-brain საზოგადოება, clock-skew.

14) კონფიგურაციის შაბლონები (მაგალითი)

yaml outbox:
poll_interval_ms: 200 batch_size: 200 order_by: occurred_at backoff:
strategy: exponential_full_jitter initial_ms: 250 max_ms: 10_000 max_attempts: 20 fairness:
per_tenant_parallelism: 4 per_key_serial: true

publisher:
rate_limit_per_sec: 500 headers:
idempotency_key: event_id schema_version: v3 dlq:
enabled: true topic: myapp. events. dlq include_metadata:
- error
- attempts
- source_table
- tenant_id
- aggregate_id

15) ინტეგრაცია საგნებთან და რუტინებთან

Outbox - „უსაფრთხოების ტრანსპორტი“ საგის ნაბიჯებისთვის: ადგილობრივი გარიგება წერს ეფექტს და გუნდს/მოვლენას; პუბლიკაცია საიმედო და დოზირებულია.
გამეორებისა და ბაჩოფის პოლიტიკოსები უნდა შეთანხმდნენ 'Retry-After' და Circuit Breaker- თან; მოერიდეთ „ქარიშხლის ქარიშხალს“.

16) ტიპიური შეცდომები

ისინი მოვლენას წერენ აფეთქების ღუმელის კომიტის შემდეგ - დანაკარგი შესაძლებელია შემოდგომაზე.
არ არსებობს ინდექსები/არქივები „outbox“ - ში, პუბლიკაციის შეფერხების ზრდა.
Pablisher 'SKIP LOCKED' გარეშე ან შარდვის გარეშე - კონკურენცია და დაბლოკვა.
მომხმარებლებს შორის იდემპოტენტურობის არარსებობა დუბლები და გვერდითი მოვლენებია.
PII ნაზავი შენიღბვის გარეშე DLQ/ლოგებში.
პუბლიკაციის ერთიანი გლობალური ეტაპი fairness- ის გარეშე - „ხმაურიანი“ ტენანტი ყველას აფერხებს.
ლაგამის მონიტორინგის არარსებობა ფარული დეგრადაციაა.

17) სტრატეგიის სწრაფი შერჩევა

საწყისი დონე: DD- დან ნახევარი, 100-500, backoff full-jitter, inbox Consumers.
მაღალი დატვირთვა: CDC გარიგების ჟურნალიდან, შარდვა 'tenant _ id/aggregate _ id', WFQ ქირაობისთვის.
მკაცრი განყოფილება: per key (mutex) სერიული გამოცემა, ტოპიკის განლაგება გასაღებით.
შესაბამისობა/PII: payload დაშიფვრა, გამოცემა DLQ- ში, რეგიონალური გარე ბოქსი.

18) ჩეკის სია გაყიდვამდე

  • დომენის ცვლილებები და ჩაწერა „Outbox“ - ში ხდება ერთ გარიგებაში.
  • პაბლიცერი ამუშავებს ბუჩქებს, იყენებს 'SKIP LOCKED', backoff ერთად ჯიტერი და ლიმიტები.
  • Consumers idempotent (ცხრილი 'inbox '/დედაპლატის ჟურნალი).
  • DLQ და უსაფრთხო რადარი.
  • lage/შეცდომების მეტრიკა და ალერტები p95/p99 ზღურბლზე.
  • საკვანძო წესრიგი გარანტირებულია (წვეულებები/სერიები).
  • არქივი/რეტენსია 'outbox' და გამოქვეყნებული ჩანაწერების გაწმენდა.
  • PII პოლიტიკა და სახელმწიფოების გადასვლის აუდიტი.
  • ტესტები კომუნასა და პუბლიკაციას შორის დაცემის, დუბლიკატებისა და წესრიგის შესახებ.
  • ღონისძიების კონტრაქტების დოკუმენტაცია (სქემები/ვერსიები/თავსებადობა).

დასკვნა

Outbox პატრონი BD-Shina- ს „მყიფე“ თაიგულს საიმედო კონვეიერად აქცევს: სახელმწიფოს ატომური ფიქსაცია გარანტირებულია (თუმც „ყოველ ჯერზე ერთხელ მაინც“) პუბლიკაციაში, imptent აბონენტები და კონტროლირებადი რედაქცია. სწორი ტელემეტრიის, ლიმიტებისა და სქემების დისციპლინით, იგი იძლევა პრაქტიკულ ექსაქტილ-ერთ ქცევას, ამცირებს განაწილებული გარიგების სირთულეს და ზრდის სისტემის სტაბილურობას წარუმატებლობებისა და პიკის დატვირთვების მიმართ.

Contact

დაგვიკავშირდით

დაგვიკავშირდით ნებისმიერი კითხვის ან მხარდაჭერისთვის.ჩვენ ყოველთვის მზად ვართ დაგეხმაროთ!

Telegram
@Gamble_GC
ინტეგრაციის დაწყება

Email — სავალდებულოა. Telegram ან WhatsApp — სურვილისამებრ.

თქვენი სახელი არასავალდებულო
Email არასავალდებულო
თემა არასავალდებულო
შეტყობინება არასავალდებულო
Telegram არასავალდებულო
@
თუ მიუთითებთ Telegram-ს — ვუპასუხებთ იქაც, დამატებით Email-ზე.
WhatsApp არასავალდებულო
ფორმატი: ქვეყნის კოდი და ნომერი (მაგალითად, +995XXXXXXXXX).

ღილაკზე დაჭერით თქვენ ეთანხმებით თქვენი მონაცემების დამუშავებას.