Транзакциялық месседжинг
Транзакциялық месседжинг - бұл жай-күйдің жергілікті өзгерістері (ДҚ/кэш) мен брокер/шинадағы хабарламалар арасындағы келісімділікті қамтамасыз ететін архитектуралық тәсілдер жиынтығы. Мақсаты: ақаулықтар, ретрациялар, масштабтау және мульти-тенанттық кезінде «хабар жоғалмаған және қайталанбаған күйде».
1) Жеткізу семантикасы
At-most-once: тез және арзан, жоғалту мүмкін, дубль жоқ.
At-least-once: хабарларды жоғалтпайды, дубль болуы мүмкін → іспеттілік талап етіледі.
(Тиімді) Exactly-once: жоғалту жоқ және бизнес-әсерлер үшін көрінетін қосарланулар жоқ, техникалар комбинациясымен қол жеткізіледі (outbox/inbox, продьюсер/консьюсер транзакциялары, дедуп).
2) Неліктен «қос жазба» қауіпті
«Алдымен ДБ-ға жазамыз, содан кейін шинаға жібереміз» (немесе керісінше) деген аңқаулық қисыны қадамдар арасында құлаған кезде үзіледі: деректер тіркелген, ал оқиға жоғалған; немесе оқиға кетті, ал деректер жоқ. Транзакциялық месседжинг бұл алшақтықты жояды.
3) Базалық паттерндер
3. 1 Outbox (өндіруші)
Бір жергілікті транзакцияда бизнес-өзгерісті және 'outbox' кестесіне жолды жазамыз; жеке паблишер outbox оқиды және ретраларымен және backoff брокеріне жариялайды. Шығындар алынып тасталды; тұтынушылардың икемділігін өшіреміз.
3. 2 Inbox/Idempotent Consumer (тұтынушы)
Эффектіні орындаудан бұрын, консюмер бастапқы кілт ретінде 'INSERT' in 'inbox (consumer, event_id)' жасайды. Кілт қайшылығы = оқиға өңделді → өткізіп жатырмыз. Осылайша «тиімді exactly-once» қол жеткізіледі.
3. 3 Оффсет транзакциясымен Read-Process-Write
Лог-бағытталған шиналар үшін үлгі: консьюмер батч оқиды, сол транзакцияда бизнес-өзгерісті және «өткен оффсетті» тіркейді. Коммиттен кейін брокер хабарламаларды тұтынылған деп есептейді. Бұл «оқылды → түсті → қайталанды» эффектінде дубльсіз жояды.
3. 4 ТСС/Сервис аралық әсерлерге арналған сағаттар
Келісілген мультишаг процесі қажет болғанда, TCC немесе сагаларды пайдаланамыз; хабарламалар - командаларды/оқиғаларды тасымалдау, ал транзакциялану - қадамдар мен өтемақылар деңгейінде.
4) Идемпотенттік продьюсерлер мен консьюмерлер
Продюсер: тұрақты 'message _ id '/' idempotency _ key', сол кілтпен қайта жіберу жазылушыларда жаңа әсер тудырмайды; кілт бойынша бірізділікті (sequence) сақтаңыз.
Консьюмер: 'inbox' + бизнес-теңсіздік (upsert/merge, соңғы нұсқасын тексеру/тексеру).
5) Тәртіп және себептері
Бір нысанның оқиғалары ретімен келуі үшін бизнес кілті бойынша партияланыңыз (мысалы, 'aggregate _ id', 'tenant _ id').
Партияның ішінде бірізді нөмірлерді/уақытша белгілерді сақтаңыз; DLQ-дан редрайвте «кілт бойынша және дәйекті түрде» сақтаңыз.
Егер жаһандық тәртіп сыни болмаса, жергілікті кілт тәртібін қамтамасыз етіңіз және домен инварианттарын белгілеңіз.
6) Оффсеттер және әсерлерді бекіту
А нұсқасы: «ДБ-ға оффсет»
«Соңғы өңделген офсетті (partition, offset)» домендік деректерді өзгерткен транзакцияға жазыңыз. Қайта қаралған кезде, қайталама әсерді болдырмай, келесі офсетпен жалғастырыңыз.
В нұсқасы: «Брокердің транзакциясы»
Кейбір брокерлер продьюсердің/консьюмердің бір транзакциясы шеңберінде хабарламалар мен оффсеттердің атомарлық жазбасын қолдайды. Егер қол жетімді болса, пайдаланыңыз, бірақ әрқашан тұтынушыдағы теңсіздікпен толықтырыңыз.
7) Ретраи, backoff, DLQ
Тек ретраибл-қателерді (таймауттар, 5xx) экспоненциалды backoff және джиттермен қайталаңыз.
Нон-ретраибл (schema/валидация) - метадеректермен (tenant, key, offset, себеп) DLQ-да бірден.
DLQ-дан редрайвды мөлшерлеңіз (batch, rate limit), қайталаудың алдында схеманы тексеріңіз, кілттің ретін сақтаңыз.
8) Мульти-тенанттық және өңірлер
'tenant _ id', 'plan', 'region' дегенді метадеректер мен топтастыру кілттеріне қосыңыз.
Per-tenant fairness: «шулы» клиент басқалардан бюджетті есептемеуі үшін жарияланымды/өңдеуді шектеңіз.
Residency: хабарларды және outboxты домен деректерімен бірдей аймақта сақтаңыз; өңіраралық репликациялар - асинхронды агрегаттар.
9) Бақылау және аудит
Трейсинг: 'event _ id '/' aggregate _ id '/' saga _ id' корреляциясы, «read → process → write/commit».
Метрика: жариялау/өңдеу (p95/p99), табыстардың үлесі, DLQ-rate, редрайвтың табысы, «телнұсқалар басылған».
Логи: табысқа қысқаша; қателерге егжей-тегжейлі (себеп, әрекет, кілт, оффсет).
Аудит: кім редрайвил/сырғанады, қандай батпен және қандай нәтижемен.
10) Қауіпсіздік және сәйкестік
Payload бағдарламасында PII-ні барынша азайтыңыз; DLQ/логиге көшіру кезінде жасырыңыз.
Сыртқы шиналар үшін хабарламаларға қол қою/шифрлау; қызметтер арасында mTLS пайдаланыңыз.
Сақтау мерзімін және «ұмытылу құқығын» басқарыңыз per tenant/region.
11) Интеграцияның үлгілік схемалары
1. Қызмет көзі (write-side)
Жергілікті транзакция: домендік жазба + outbox.
Паблишер: батчи, 'SKIP LOCKED', backoff, per tenant лимиттері.
lag 'now − occurred_at' мониторингі.
2. Қызмет тұтынушы (read-side)
Батч оқу → 'INSERT inbox (consumer, event_id)' → әрекеті табысты болса, эффекті орындалады.
Дәл сол транзакцияда «өткен оффсетті» (А нұсқасы) белгілейміз немесе брокердің транзакциясына сүйенеміз (В нұсқасы).
Қате: саясат бойынша ретрай немесе DLQ.
3. Проекция/материалданған түрі
Тек қана демпотенттік апдейттер (upsert), дедуптың ықшам кілттері, бақылау сомаларын мерзімді салыстыру.
12) Конфигурациялық үлгілер (мысал)
yaml producer:
idempotency_key: event_id partition_key: "{tenant_id}:{aggregate_id}"
retry:
max_attempts: 8 initial_ms: 200 max_ms: 8000 strategy: exponential_full_jitter
consumer:
batch: 500 offset_commit: "with_domain_tx" # или "broker_tx"
inbox_enabled: true concurrency_per_partition: 4 dlq:
enabled: true batch_redrive: 200 rate_limit_per_sec: 50 order_by_key: true
observability:
metrics:
- processing_lag_ms
- publish_success_ratio
- dlq_rate
- redrive_success_ratio tracing_tags: [event_id, tenant_id, aggregate_id, partition, offset]
13) Азық-түлік алдындағы чек-парағы
- «Қос жазба» жойылды: продюсердегі outbox немесе оффсет пен эффектті консьюмерде бір транзакцияда бекіту.
- Идемпотенттік консьюмер: 'inbox '/дедуп-журнал, операциялардың бизнес-идемпотенттілігі.
- Бизнес кілті бойынша партияландыру, жергілікті тәртіп сақталған.
- Backoff + джиттермен ретрайлер, қателерді жіктеу, бай метадеректермен DLQ.
- Редрайв дозаланған, қауіпсіз; ойнатқыштар бар.
- Мульти-тенанттық лимиттер мен басымдықтар; тегтер 'tenant _ id/plan/region'.
- Телеметрия: лагтар, табыстардың үлесі, «телнұсқалар басылған», p95/p99 бойынша алерталар.
- PII/ретеншн/шифрлау саясаты сақталған.
- Тесттер: қадамдар арасында құлау, телнұсқалар, кілт бойынша тәртіп, жаппай редрайв.
14) Типтік қателер
outbox/оффсет транзакциясынсыз бөлек қадамдармен шинаға жіберу және ДҚ-ға жазу.
Консьюмер демпотенттігі жоқ → жанама әсерлерін қайталайды.
Жаһандық тәртіп «қалай болғанда да» - қымбат және сирек ақталады; кілт бойынша тәртіп жеткілікті.
Лимитсіз жаппай редрайв → екінші оқыс оқиға.
Трейсингтің/лаг-метриктің болмауы → «жасырын тозу».
DLQ/логтардағы PII араластыру.
15) Жылдам рецепттер
SaaS-оқиғалар: Outbox + демпотенттік консюмер (inbox), 'tenant _ id: aggregate _ id' бойынша партиялануы.
ETL/проекциялар: Бір транзакциядағы оффсеттерді белгілеумен Read-process-write, батчи 500-1000, upsert.
Жоғары жүктеме: паблишерлерді шардалау, 'SKIP LOCKED', WFQ per tenant, лагты бақылау.
Қатаң комплаенс-аймақ: аймақтық outbox, payload шифрлау, ретеншн және редрайвтар аудиті.
Қорытынды
Транзакциялық месседжинг - бұл деректер мен хабарларды біріктіру тәртібі. Outbox/inbox, теңсіздік, оффсеттерді бекітуді эффекттермен және DLQ-мен басқарылатын ретраялармен біріктіру арқылы сіз жаһандық бұғаттаусыз практикалық exactly-once мінез-құлыпты аласыз және тіпті ақаулықтар, шыңдар және күрделі көп тенантты пайдалану кезінде де SLO-ны сақтайсыз.