awesome-everything EN
↑ Обратно к восхождению

Очереди, потоки, события

Outbox: построй крах-безопасный конвейер событий

Суть Практический проект — построй сервис заказов, который убирает dual-write через transactional outbox, шлёт события polling relay и доказывает, что ни одно событие не потеряно и не применено дважды под инъекцией крахов.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 240 min

Читать про разрыв dual-write — не то же самое, что увидеть, как событие исчезает, а затем закрыть дыру самому. Построй небольшой сервис заказов, докажи, что он теряет события наивным способом, затем добавь transactional outbox плюс idempotent-консьюмера и покажи — с намеренно инъецированными крахами — что ничего не потеряно и ничего не применено дважды.

Цель

Преврати ментальную модель юнита в работающий конвейер: пиши бизнес-строку и outbox-строку в одной transaction, шли строки крах-безопасным polling relay, масштабируй relay без двойной публикации и подтверди, что гарантия at-least-once держится сквозь под инъецированными сбоями.

Проект
0 из 8
Цель

Построй сервис заказов, который публикует событие OrderPlaced для каждого закоммиченного заказа с нулём потерянных событий под инъекцией крахов, используя transactional outbox и polling relay, и докажи гарантию at-least-once idempotent-консьюмером, который никогда не применяет дважды.

Требования
Критерии приёмки
  • Сравнение до/после: наивный dual-write теряет хотя бы одно событие под инъекцией краха; outbox-версия теряет ноль при том же расписании крахов.
  • Доказательство (логи или счётчик), что relay доставил хотя бы одно событие более одного раза под инъекцией краха, И что побочный эффект всё равно применён ровно один раз — доказывая идемпотентность консьюмера.
  • При нескольких работающих репликах relay ни один event id не публикуется дважды за один проход — SKIP LOCKED захватывает непересекающиеся батчи.
  • Краткий разбор: где был разрыв dual-write, почему одна локальная transaction его закрывает, почему доставка всё ещё at-least-once и как консьюмер дедупит.
Senior-стретч
  • Замени polling relay на CDC relay (Debezium tailing WAL или логическая репликация твоей БД) и измерь падение сквозной задержки против polling с интервалом 500мс.
  • Добавь очистку outbox, не вредящую пути записи: либо батчевые удаления старых sent-строк, либо дневные партиции, reaping через DROP PARTITION, и покажи, что poll неотправленных строк остаётся быстрым по мере роста таблицы.
  • Сохрани порядок по aggregate: ключуй события по aggregate id, чтобы все события одного заказа приземлялись в одну партицию и одному воркеру, и продемонстрируй, что порядок держится даже с несколькими relay.
  • Добавь sweep ретенции inbox (дропай обработанные event id старше N часов) и порассуждай об окне: слишком короткое рискует переприменить очень поздний дубликат, слишком длинное раздувает таблицу дедупа.
Итог

Это конвейер, к которому ты потянешься всякий раз, когда запись обязана надёжно триггерить уведомление: докажи, что наивный dual-write теряет события, затем пиши бизнес-строку и outbox-строку в одной локальной transaction, чтобы намерение публиковать было долговечным, шли строки relay, который захватывает непересекающиеся батчи через SKIP LOCKED, и делай консьюмеров idempotent по стабильному event id, чтобы неизбежный дубликат at-least-once был no-op. Построй это раз с намеренно инъецированными крахами, и production-версия — никогда тихо не теряющая запись — станет мышечной памятью.

Продолжить восхождение ↑Change-Data Capture: стриминг write-ahead log без переполнения диска
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.