Bosh sahifa Wiki Outbox pattern

Outbox pattern

Outbox pattern — database’dagi biznes o‘zgarishi bilan tashqi message brokerga yuboriladigan eventni bitta local transaction ichida muvofiqlashtirish usulidir. Application business row va outbox rowni atomik yozadi; alohida relay commit qilingan outbox eventlarini brokerga yetkazadi. Bu xavfli dual-write oralig‘ini kamaytiradi.

Dual-write muammosi

Application avval databasega yozib, keyin message publish qilsa database commitdan keyin process yiqilishi mumkin. Data yangilanadi, event yuborilmaydi. Avval event yuborilsa, keyingi database rollback consumerga mavjud bo‘lmagan o‘zgarishni ko‘rsatadi.

Distributed transaction broker va database orasida atomic commit berishi mumkin, ammo barcha platforma qo‘llamaydi va operatsion murakkab. Outbox bitta database transactioniga tayanadi.

Jadval tuzilishi

Outbox row odatda event ID, aggregate type va ID, event type, payload, schema version, created time va publish holatini saqlaydi:

id | aggregate_id | type | payload | created_at | published_at

Business update va INSERT INTO outbox aynan bir transactionda bajariladi. Transaction rollback bo‘lsa ikkalasi ham yo‘q. Event ID barqaror va globally unique bo‘lib, consumer deduplication uchun ishlatadi.

Relay usullari

Polling publisher unpublished satrlarni batchda oladi, brokerga yuboradi va published deb belgilaydi. Bir nechta worker FOR UPDATE SKIP LOCKED kabi mexanizm bilan rowlarni bo‘lishishi mumkin. Lockni broker acknowledgment davomida uzoq ushlash database contention keltiradi.

Change Data Capture transaction logdan outbox insertlarni o‘qib brokerga chiqaradi. Bu polling loadini kamaytiradi va commit tartibiga yaqin oqim beradi. CDC connector offseti, schema va failover alohida boshqariladi.

At-least-once

Relay eventni brokerga yuborib, published_at yozishdan oldin yiqilsa event qayta yuboriladi. Shu sabab outbox odatda at-least-once delivery beradi. Consumer event ID bo‘yicha idempotent ishlashi yoki inbox jadvalida processed ID saqlashi kerak.

Publisher brokerning idempotent producer imkoniyatidan foydalanishi mumkin, ammo end-to-end side effect baribir consumer contractiga bog‘liq. Email yuborish yoki tashqi API chaqiruvida idempotency key kerak.

Tartib

Bir aggregate eventlari version yoki sequence bilan tartiblanadi. Parallel relay global orderni kafolatlamasligi mumkin. Broker partition key sifatida aggregate ID ishlatilsa shu entity doirasida order saqlanadi.

Consumer version 5ni version 4dan oldin olsa buffer, reject yoki state-based idempotent update siyosatidan foydalanadi. Global transaction order talab qilish throughputni keskin cheklaydi.

Payload

Outbox notification faqat entity IDni berib, consumer keyin source database’dan o‘qishi mumkin. Bu database exposure va vaqt race’ini keltiradi. Event-carried state transfer zarur fieldlarni payloadga qo‘shadi, consumer source’ga bog‘lanmaydi.

Payload immutable va versionlangan bo‘ladi. Shaxsiy ma’lumot broker hamda retention bo‘ylab ko‘payadi, shu sabab minimal field va classification ishlatiladi. Katta binary object event ichida emas, access-controlled object reference bilan uzatiladi.

Cleanup

Published rowlar cheksiz o‘smasligi uchun retention asosida partition drop yoki batch delete qilinadi. Consumer replay talabi broker retentioniga yoki alohida event archivega tayanadi. Outbox operatsion queue bo‘lsa uni abadiy event store deb qabul qilinmaydi.

Monitoring oldest unpublished age, pending count, publish latency, retry va dead-letter holatini ko‘rsatadi. Relay ishlamay qolsa business transactionlar davom etishi, backlog esa diskni to‘ldirishi mumkin.

Bog‘liq tushunchalar

Transactional outbox, Change Data Capture, Message broker, Idempotency, Inbox pattern, Event-driven architecture, Database transaction