← Назад к вопросам

Что используется для гарантии доставки?

1.6 Junior🔥 41 комментариев
#Требования и документация

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Механизмы гарантии доставки в распределенных системах

Гарантия доставки (Delivery Guarantee) — это критический аспект надежности распределенных систем, особенно в архитектурах микросервисов. Существует несколько подходов и паттернов.

Классификация уровней доставки

At Most Once (не более одного раза)

  • Сообщение может быть потеряно
  • Но не может быть обработано дважды
  • Когда использовать: неважные уведомления, аналитика
  • Пример: отправка notification'а о новом комментарии

At Least Once (не менее одного раза)

  • Гарантия что сообщение будет доставлено
  • Но может быть обработано несколько раз
  • Когда использовать: финансовые операции, важные события
  • Требует обработки дублей (idempotency)

Exactly Once (ровно один раз)

  • Идеальный случай — сообщение доставлено ровно один раз
  • Сложно реализовать и ресурсоемко
  • Когда использовать: критические операции (платежи, транзакции)

Основные механизмы гарантии доставки

1. Message Brokers (Очереди сообщений)

RabbitMQ:

  • Persistent очереди на диске
  • Подтверждение доставки (ACK)
  • Dead Letter Exchange для неудачных сообщений
  • Гарантирует At Least Once при правильной конфигурации
Producer → RabbitMQ (persistent) → Consumer
                ↓
          (на диск)

Apache Kafka:

  • Репликация между brokers (replication factor)
  • Consumer offset tracking
  • Retention policy для replay сообщений
  • Leader election для fault tolerance
  • Гарантирует At Least Once per partition

AWS SQS / Google Pub/Sub:

  • Автоматическая репликация
  • Visibility timeout
  • Dead letter queue для неудачных сообщений
  • Managed сервис без операционной нагрузки

2. Persistent Storage

Выписание в базу данных:

INSERT INTO outbox (event_id, aggregate_id, event_type, payload, created_at)
VALUES (?, ?, ?, ?, NOW());

Паттерн Outbox:

  • При обработке события записываем его в таблицу outbox в ОДНОЙ транзакции с изменением основного сущности
  • Separate процесс читает из outbox и отправляет сообщение
  • После успешной отправки помечаем как processed
  • При сбое сообщение пересылается автоматически

Это гарантирует что если бизнес-операция записана в БД, сообщение будет доставлено.

3. Асинхронные очереди задач

Celery (Python):

@app.task(bind=True, max_retries=3)
def process_payment(self, payment_id):
    try:
        payment = Payment.get(payment_id)
        payment.process()
    except Exception as exc:
        raise self.retry(exc=exc, countdown=60)

Bull (Node.js):

  • Очередь на Redis
  • Automatic retry с exponential backoff
  • Failed jobs для manual review
  • Job concurrency control

4. Idempotency (Идемпотентность)

Гарантирует что двойная обработка = нормально:

# Идемпотентный ключ
idempotency_key = request.headers.get('Idempotency-Key')

# Проверяем была ли операция уже выполнена
cached_result = cache.get(idempotency_key)
if cached_result:
    return cached_result

# Выполняем операцию
result = process_payment(order_id)

# Кешируем результат
cache.set(idempotency_key, result, ttl=24h)
return result

Это критично для:

  • API платежей
  • Операций с инвентарем
  • Создания заказов

5. Retry Logic (Логика переповторов)

Exponential Backoff:

  • Первый попыт: сразу
  • Вторая попытка: через 1 сек
  • Третья: через 4 сек (2²)
  • Четвертая: через 16 сек (2⁴)
  • И так далее...
  • Максимум: не более 10 попыток

Правила переповторов:

  • Retry только на временные ошибки (5xx, timeout, network error)
  • Не retry на постоянные ошибки (4xx, validation error)
  • Иметь максимум попыток
  • Логировать все попытки

6. Circuit Breaker (Автоматический выключатель)

Состояния:

  • Closed — все хорошо, запросы проходят
  • Open — сервис недоступен, запросы отклоняются сразу
  • Half-Open — проверяем доступность через пробный запрос

Это предотвращает cascade failures когда downstream сервис не отвечает.

7. Distributed Transactions

Saga Pattern:

  • Последовательность операций, каждая с компенсацией
  • Если одна операция не прошла — откатываем предыдущие
charge_card → reserve_inventory → create_order
    ↓              ↓              ↓
 [fail] ← [compensate] ← [compensate]

8. Health Checks и Monitoring

Обязательно мониторить:

  • Размер очередей (если растет → потребитель медленный)
  • Время доставки сообщений
  • Fail rate и reasons
  • Dead Letter Queue
  • Lag консьюмеров

Практический пример: Критическая операция

Сценарий: Обработка платежа

1. Платеж приходит через API
2. Создаем запись в БД: INSERT INTO payments
3. Записываем событие в outbox таблицу (в одной транзакции)
4. Возвращаем 202 Accepted клиенту
5. Background worker читает из outbox
6. Отправляет платеж в payment gateway
7. На response от gateway обновляем БД
8. Помечаем событие в outbox как processed
9. Если worker упал — при перезагрузке прочитает необработанные события
10. Если gateway вернул ошибку — используем retry logic
11. Idempotency key на payment gateway гарантирует что не будет двойной траты

Выбор механизма

Simple случай (некритичные данные):

  • Прямой HTTP запрос с retry logic
  • Кешированный результат

Medium (важные операции):

  • RabbitMQ / SQS с persistent storage
  • Idempotency key
  • Retry logic

Critical (финансовые транзакции):

  • Outbox паттерн
  • Distributed transaction (Saga)
  • Idempotency key
  • Health checks и мониторинг
  • Backups и disaster recovery

Вывод: Гарантия доставки — это не один механизм, а комбинация паттернов и практик, подобранных под риск уровень операции.

Что используется для гарантии доставки? | PrepBro