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

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

Гарантии доставки: построй краш-устойчивый платёжный консьюмер

Суть Практический проект — построй платёжный консьюмер, переживающий краши без двойных списаний, и докажи effectively-once под инжектированными сбоями с числами дубликатов до/после.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 240 min

Читать о двойных списаниях — не то же, что остановить одно. Построй небольшой платёжный консьюмер на очереди at-least-once, загони его в каждое плечо сбоев инжектированными крашами и неправильными таймаутами и укрепляй, пока число дубликатов не станет ровно нулём — с доказательством на каждом шаге.

Цель

Преврати ментальную модель юнита в воспроизводимый инженерный цикл: воспроизведи дубликаты и потери намеренно, добавь INSERT-first транзакционный дедуп плюс Idempotency-Key, закрой dual-write на стороне продюсера через outbox и докажи effectively-once под chaos с числами до/после.

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

Построй платёжный консьюмер на очереди at-least-once (SQS, RabbitMQ или Kafka), достигающий effectively-once: ноль двойных списаний и ноль потерянных событий под инжектированными крашами консьюмера, истечением visibility timeout и сбоями на стороне продюсера — доказанное измеренными числами дубликатов и потерь, а не утверждениями.

Требования
Критерии приёмки
  • Таблица до/после: число двойных списаний и число потерянных событий, измеренные под идентичным chaos-прогоном (убить консьюмер на середине обработки, истечь таймаут, уронить публикацию) — наивная версия против укреплённой. Укреплённая должна показать ноль и того и другого.
  • Демонстрация, что убийство консьюмера ПОСЛЕ коммита БД, но ДО ack вызывает передоставку, которая тихо дедуплицируется (нарушение UNIQUE -> откат -> ack), при этом метрика dedup_hit_rate регистрирует поимку.
  • Демонстрация, что уронённая/упавшая публикация на стороне продюсера НЕ теряет событие, потому что строка outbox остаётся pending и sender её переопубликует.
  • Короткое описание, сопоставляющее каждый фикс с плечом сбоя, которое он закрывает (плечо 1 / плечо 3 / dual-write / таймаут), и называющее, почему именно идемпотентность консьюмера — а не настройка брокера — это несущая гарантия.
Senior-стретч
  • Добавь idempotent producer + транзакции Kafka на пути внутри Kafka и измерь стоимость пропускной способности (~3% против ~20-30%); затем покажи, что кросс-системной записи в Postgres ВСЁ РАВНО нужен дедуп консьюмера, доказывая, где заканчивается граница транзакции Kafka.
  • Построй chaos-харнесс, который случайно убивает консьюмер на каждом шаге (до списания, после списания до коммита, после коммита до ack) в цикле на 1000 сообщений, и проверь, что charges-per-order == 1 для каждого заказа в конце.
  • Добавь одностраничный on-call runbook: как читать скачок dedup_hit_rate, правило SQS visibility timeout, чеклист redrive DLQ (снапшот, аудит выборки, rate-limit) и дерево решений дубликат-против-потери.
  • Замени поллер outbox на CDC (Debezium, читающий WAL) и сравни задержку и операционную нагрузку с поллинг-sender'ом.
Итог

Это цикл, который ты запускаешь в каждом реальном инциденте гарантий доставки: воспроизведи дубликат или потерю намеренно, определи плечо сбоя, примени структурный фикс (INSERT-first транзакционный дедуп, стабильный Idempotency-Key, outbox для dual-write, таймаут под обработку) и проверь измеренными числами до/после под chaos — никогда утверждениями. Построй это раз на игрушечном платёжном консьюмере, и production-версия становится мышечной памятью: доставка at-least-once, обработка effectively-once, корректность обеспечена в консьюмере.

Продолжить восхождение ↑Kafka partitions: единица параллелизма, порядка и дверь в одну сторону
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.