Гарантии доставки
Гарантии доставки определяют, может ли сообщение быть потеряно или продублировано: 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-once | At-least-once | Exactly-once |
|---|---|---|---|
| Потеря данных | Да | Нет | Нет |
| Дубликаты | Нет | Да | Нет |
| Производительность | Высокая | Средняя | Низкая |
| Сложность | Низкая | Средняя | Высокая |
| Требования к получателю | Минимальные | Идемпотентность | Идемпотентность + координация |
Как гарантии реализуются в брокерах
Kafka
| Настройка | Гарантия |
|---|---|
acks=0 | At-most-once |
acks=1 или all | At-least-once |
enable.idempotence=true + транзакции | Exactly-once (в пределах одной партиции) |
RabbitMQ
| Настройка | Гарантия |
|---|---|
| Без publisher confirms, без consumer acks | At-most-once |
| Publisher confirms + consumer acks | At-least-once |
| Идемпотентные потребители | Exactly-once (эмулируется) |
AWS SQS
| Тип очереди | Гарантия |
|---|---|
| Standard | At-least-once |
| FIFO | Exactly-once (в рамках очереди) |
Идемпотентность
Что это
Свойство операции, при котором повторное выполнение даёт тот же результат, что и однократное.
Как реализовать
Получатель:
1. Получить сообщение с idempotency_key
2. Проверить в хранилище: ключ уже обработан?
3. Если да → пропустить, вернуть OK
4. Если нет → обработать, сохранить ключХранилище для ключей
| Вариант | Плюсы | Минусы |
|---|---|---|
| База данных | Надёжно | Медленно |
| Redis | Быстро | Может потерять данные |
| Брокер (транзакции) | Встроено | Не везде есть |
Практические рекомендации
Выбор гарантии
| Если | Выбирайте |
|---|---|
| Логи, метрики | At-most-once |
| Потеря данных недопустима, дубликаты можно обработать | At-least-once + идемпотентность |
| Ни потери, ни дубликаты недопустимы | Exactly-once (если поддерживается) |
Что делать, если exactly-once не поддерживается
- Использовать at-least-once
- Сделать получателя идемпотентным
- Дубликаты не страшны
Пример: Платёжная система
| Компонент | Гарантия | Почему |
|---|---|---|
| Веб-сайт → брокер | 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 от брокера гарантирует доставку, но не обработку. Обработка должна быть идемпотентной.
Резюме
Три уровня гарантий: at-most-once (потеря возможна), at-least-once (дубликаты возможны), exactly-once (ни того, ни другого).
At-most-once: быстро, но данные могут теряться. Для логов, метрик.
At-least-once: надёжно, но возможны дубликаты. Для большинства сценариев.
Exactly-once: максимальная надёжность, но медленно и сложно. Для финансов, критических данных.
Идемпотентность — ключевое требование для at-least-once и exactly-once. Обработка должна быть устойчива к дубликатам.
Компромисс: надёжность vs производительность. Exactly-once дороже.