Outbox pattern на собеседовании системного аналитика
Карьерник — Duolingo для аналитиков: 10 минут в день тренируй SQL, Python, A/B, статистику, метрики и ещё 3 темы собеса. 1500+ вопросов в Telegram-боте. Бесплатно.
Содержание:
Dual write problem
Service хочет:
- Save в БД.
- Publish event в Kafka.
BEGIN;
INSERT INTO orders ...;
COMMIT;
publish_event("OrderCreated"); # ← может failЕсли publish fails — DB updated, event lost. Inconsistency.
Naive «publish first, then save» — opposite problem.
Outbox pattern
Сохранить event в same transaction что и business data.
BEGIN;
INSERT INTO orders ...;
INSERT INTO outbox (event_type, payload) VALUES ('OrderCreated', '...');
COMMIT;Both saved или both rolled back. Atomic.
Отдельный worker / CDC reads outbox → publishes Kafka.
Polling implementation
Worker loop:
SELECT * FROM outbox WHERE published = false LIMIT 100;
For каждого event:
Publish to Kafka.
UPDATE outbox SET published = true WHERE id = ...;Pros: simple.
Cons: polling overhead. Latency depends на interval.
Optimizations:
- Index на
published, created_at. - Mark published, archive old → keep table small.
- Multiple workers с lock for atomicity.
CDC implementation
Debezium reads Postgres WAL → outbox table inserts → publish to Kafka automatically.
Pros: низкая latency, no polling.
Cons: requires Debezium infra.
Стандарт modern setup.
SMT (Single Message Transform). Debezium plugin extracts payload field → publishes на topic from event_type.
Inbox pattern
Symmetric. Consumer:
Receive event from Kafka.
INSERT INTO inbox (event_id, payload) — IGNORE если duplicate.
COMMIT.
Worker процессит inbox events.Idempotency на receiver. Защищает от duplicate Kafka messages.
Связанные темы
- 2PC vs Saga для SA
- Event-driven архитектура для SA
- CDC и Debezium для DE
- Idempotency key для SA
- Подготовка к собесу системного аналитика
FAQ
Это официальная информация?
Нет. Статья основана на работах Chris Richardson (microservices.io), Debezium docs.
Тренируйте системный анализ — откройте тренажёр с 1500+ вопросами для собесов.