Перейти к содержанию

Transactional Outbox для финансовых операций

Раздел 05 · Редакционный стандарт

Тип материала — референсная архитектура. HYPOTHETICAL — схемы и операции. INFERENCE — инженерные рекомендации и критерии выбора. Внешние контракты ограничены источниками ниже.

Бизнес-задача

Довести факт committed posting до downstream при сбоях relay.

Требования

Хранить backlog до доказанного покрытия. Отделить событие и команду. Поддержать исторический replay.

Поток данных и владение состоянием

flowchart LR
 A["Posting API"] --> B["Ledger DB transaction"]
 B --> C["Outbox table"]
 C --> D["Relay and Kafka"]
 D --> E["Consumer inbox"]

Ledger владеет фактом. Outbox хранит намерение публикации.

Транзакционные границы

Journal и outbox row фиксируются вместе. Kafka ACK и relay marker отделены. Inbox и effect фиксируются вместе в target.

Порядок и идемпотентность

Stable event ID и aggregate revision. Consumer проверяет gaps, если delta зависит от предшественника.

Нормальная последовательность

sequenceDiagram
 participant A as Posting API
 participant B as Ledger DB transaction
 participant C as Outbox table
 participant D as Relay and Kafka
 A->>B: Submit journal and publish intent
 B->>C: Insert outbox row in ledger transaction
 C-->>B: Return committed journal and event ID
 B->>D: Publish durable event to broker

Отказ и восстановление

sequenceDiagram
 participant B as Ledger DB transaction
 participant C as Outbox table
 participant E as Recovery operator
 B->>C: Broker ACK is lost before relay marker
 Note over B,C: Outcome becomes uncertain
 E->>C: Recover retained outbox row and resend same event ID
 E->>B: Resume from verified boundary

Сбой после broker ACK до marker создаёт повтор. При потере WAL slot восстановить покрытие через сохранённый outbox.

Сверка

Сопоставить journal IDs, outbox IDs и consumer dispositions по cut.

Граница очистки. Outbox identity включается в record key или header и сохраняется при каждой попытке. Публикующий worker хранит lease или claim для ограничения параллельных повторов. Истечение lease допускает повтор и потому не заменяет dedup. После отправки сверка проверяет event ID по consumer disposition. Compaction или удаление journal events требует явного покрытия archive и согласованного срока replay.

Наблюдаемость

Oldest backlog, WAL pressure и duplicate rate.

Безопасность и применимость требований

Минимизировать payload и ограничить ACL.

Альтернативы и trade-offs

Polling уменьшает зависимость от WAL. CDC снижает polling I/O.

Вопросы на собеседовании

Зачем ждать ACK перед marker? Иначе crash между marker и send оставит потерю.

Первичные источники