Перейти к содержимому

Гарантии доставки

Гарантии доставки определяют, может ли сообщение быть потеряно или продублировано: at-most-once (возможна потеря, но нет дубликатов) — для логов и метрик, at-least-once (нет потери, возможны дубликаты) — для большинства сценариев при идемпотентной обработке, exactly-once (ни потери, ни дубликатов) — для финансов и критических данных, но ценой производительности и сложности.

Введение: Три обещания почтальона

Представьте, что вы отправляете ценное письмо. Почтальон может дать разные гарантии.

“Я брошу письмо в ящик, и забуду. Может, дойдёт, может, нет”. Это at-most-once (не более одного раза).

“Я буду пытаться доставить письмо, пока не получу подтверждение. Если вы не подпишете уведомление, я приду снова. Но если вы подпишете, а я ошибся, письмо может прийти дважды”. Это at-least-once (не менее одного раза).

“Я лично вручу письмо адресату под расписку, и буду сверять номера, чтобы исключить дубликаты. Письмо дойдёт ровно один раз”. Это exactly-once (ровно один раз).

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

Для системного аналитика выбор гарантии доставки — это компромисс между надёжностью и производительностью. Exactly-once — самая надёжная, но самая медленная и дорогая. At-most-once — самая быстрая, но данные могут теряться.

Три уровня гарантий

ГарантияПотеря данныхДублированиеПроизводительностьТипичное применение
At-most-onceДопустимаНетВысокаяЛоги, метрики
At-least-onceНетДопустимоСредняяБольшинство сценариев
Exactly-onceНетНетНизкаяФинансы, критические данные

At-most-once (не более одного раза)

Что это

Сообщение может быть доставлено ноль или один раз. Если доставка не удалась, сообщение теряется. Дубликатов не бывает.

Как работает

Отправитель отправляет сообщение и не ждёт подтверждения. Брокер не хранит сообщение после отправки.

    sequenceDiagram
    participant A as Отправитель
    participant B as Брокер
    participant C as Получатель
    
    A->>B: Отправить
    B->>C: Отправить (без подтверждения)
    Note over A,C: Если C недоступен, сообщение теряется
  

Когда использовать

СценарийПочему
ЛогиПотеря одного лога не страшна
МетрикиПропуск одного измерения не критичен
Сенсорные данныеМиллионы показаний, потеря одного не важна
Высокая производительностьНет накладных расходов на подтверждения

Примеры брокеров

  • Kafka (с acks=0)
  • RabbitMQ (без publisher confirms)
  • UDP (не брокер, но аналогично)

 acks – это параметр, который определяет, сколько подтверждений от брокеров требуется продюсеру для того, чтобы считать сообщение успешно отправленным. Он позволяет балансировать между надёжностью доставки и производительностью.

At-least-once (не менее одного раза)

Что это

Сообщение будет доставлено один или более раз. Дубликаты возможны. Потери данных исключены.

Как работает

Отправитель ждёт подтверждения от брокера. Получатель подтверждает обработку. Если подтверждение не получено, брокер повторяет доставку.

    sequenceDiagram
    participant A as Отправитель
    participant B as Брокер
    participant C as Получатель
    
    A->>B: Отправить
    B-->>A: ACK (сохранено)
    B->>C: Отправить
    C-->>B: ACK (обработано)
    
    Note over B: Если ACK от C не получен
    B->>C: Повторная отправка
  

Гарантии

ГарантияЗначение
Не потеряетсяДа
Не продублируетсяНет

Почему возникают дубликаты

    sequenceDiagram
    participant B as Брокер
    participant C as Получатель
    
    B->>C: Сообщение
    C->>C: Обработка (успешно)
    C--x B: ACK потерялся в сети
    B->>C: Повторная отправка
    C->>C: Обработка снова (дубликат)
  

Когда использовать

СценарийПочему
Большинство сценариевПотеря данных недопустима
Обработка заказовЗаказ не должен потеряться
Очереди задачЗадача должна быть выполнена
УведомленияПисьмо должно быть отправлено

Требование к получателю

Идемпотентность — обработка должна быть устойчива к дубликатам.

Обработка платежа:
  - Проверить, не обработан ли уже этот платеж (по idempotency key)
  - Если обработан — пропустить
  - Если нет — обработать

Примеры брокеров

  • Kafka (по умолчанию, acks=1 или all)
  • RabbitMQ (с publisher confirms + consumer acks)
  • AWS SQS (по умолчанию)

Exactly-once (ровно один раз)

Что это

Сообщение будет доставлено ровно один раз. Ни потерь, ни дубликатов.

Как работает

Требует координации между отправителем, брокером и получателем. Используются идемпотентные продюсеры, транзакции, уникальные идентификаторы.

    sequenceDiagram
    participant A as Отправитель
    participant B as Брокер
    participant C as Получатель
    
    A->>B: Отправить (с idempotency key)
    B-->>A: ACK (сохранено, ключ запомнен)
    B->>C: Отправить (с идентификатором)
    C-->>B: ACK (обработано, id запомнен)
    
    Note over A: Повтор с тем же ключом
    A->>B: Отправить (тот же ключ)
    B-->>A: OK (уже было, не дублируем)
  

Гарантии

ГарантияЗначение
Не потеряетсяДа
Не продублируетсяДа

Цена exactly-once

ЦенаОбъяснение
ПроизводительностьЗначительно ниже
СложностьНужна координация
СовместимостьНе все брокеры поддерживают

Когда использовать

СценарийПочему
Финансовые транзакцииДеньги не должны теряться или удваиваться
ИнвентаризацияТовар не должен списаться дважды
БронированиеМесто не должно продаться дважды

Примеры брокеров

  • Kafka (с идемпотентным продюсером + транзакции)
  • RabbitMQ (нет нативной поддержки)
  • AWS SQS FIFO (exactly-once в рамках очереди)

Сравнение гарантий

ХарактеристикаAt-most-onceAt-least-onceExactly-once
Потеря данныхДаНетНет
ДубликатыНетДаНет
ПроизводительностьВысокаяСредняяНизкая
СложностьНизкаяСредняяВысокая
Требования к получателюМинимальныеИдемпотентностьИдемпотентность + координация

Как гарантии реализуются в брокерах

Kafka

НастройкаГарантия
acks=0At-most-once
acks=1 или allAt-least-once
enable.idempotence=true + транзакцииExactly-once (в пределах одной партиции)

RabbitMQ

НастройкаГарантия
Без publisher confirms, без consumer acksAt-most-once
Publisher confirms + consumer acksAt-least-once
Идемпотентные потребителиExactly-once (эмулируется)

AWS SQS

Тип очередиГарантия
StandardAt-least-once
FIFOExactly-once (в рамках очереди)

Идемпотентность

Что это

Свойство операции, при котором повторное выполнение даёт тот же результат, что и однократное.

Как реализовать

Получатель:
  1. Получить сообщение с idempotency_key
  2. Проверить в хранилище: ключ уже обработан?
  3. Если да → пропустить, вернуть OK
  4. Если нет → обработать, сохранить ключ

Хранилище для ключей

ВариантПлюсыМинусы
База данныхНадёжноМедленно
RedisБыстроМожет потерять данные
Брокер (транзакции)ВстроеноНе везде есть

Практические рекомендации

Выбор гарантии

ЕслиВыбирайте
Логи, метрикиAt-most-once
Потеря данных недопустима, дубликаты можно обработатьAt-least-once + идемпотентность
Ни потери, ни дубликаты недопустимыExactly-once (если поддерживается)

Что делать, если exactly-once не поддерживается

  1. Использовать at-least-once
  2. Сделать получателя идемпотентным
  3. Дубликаты не страшны

Пример: Платёжная система

КомпонентГарантияПочему
Веб-сайт → брокерAt-least-onceЗаказ не должен потеряться
Брокер → платёжный шлюзAt-least-onceПлатёж не должен потеряться
Обработка платежаИдемпотентностьПовтор платежа не создаст дубликат

Распространённые ошибки

Ошибка 1: Exactly-once везде

Пытаются использовать exactly-once для логов.

Решение: At-most-once достаточно.

Ошибка 2: At-most-once для критичных данных

Используют at-most-once для заказов. Сообщения теряются.

Решение: At-least-once.

Ошибка 3: Нет идемпотентности при at-least-once

Дубликаты приводят к двойной обработке.

Решение: Идемпотентность.

Ошибка 4: Exactly-once без тестирования

Думают, что exactly-once решает все проблемы, но не тестируют сценарии с падениями.

Решение: Нагрузочное тестирование с симуляцией сбоев.

Ошибка 5: Путают гарантии брокера и обработки

Думают, что exactly-once от брокера означает exactly-once обработки.

Решение: Exactly-once от брокера гарантирует доставку, но не обработку. Обработка должна быть идемпотентной.

Резюме

  1. Три уровня гарантий: at-most-once (потеря возможна), at-least-once (дубликаты возможны), exactly-once (ни того, ни другого).

  2. At-most-once: быстро, но данные могут теряться. Для логов, метрик.

  3. At-least-once: надёжно, но возможны дубликаты. Для большинства сценариев.

  4. Exactly-once: максимальная надёжность, но медленно и сложно. Для финансов, критических данных.

  5. Идемпотентность — ключевое требование для at-least-once и exactly-once. Обработка должна быть устойчива к дубликатам.

  6. Компромисс: надёжность vs производительность. Exactly-once дороже.

Проверка знаний

Вопрос 1 из 4
Что означает at-most-once?
Что означает at-least-once?
Почему exactly-once считается сложной гарантией?
Какое практическое следствие имеет at-least-once для потребителя?

Вопросы, где были ошибки