Карта / Kafka / Гарантии доставки

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

Гарантия доставки отвечает на вопрос: может ли сообщение потеряться или обработаться дважды. Это критичный выбор — для платежей “дважды” недопустимо, для уведомлений о новой публикации — не страшно.

ГарантияЧто значитРиск
At-most-onceсообщение доставится максимум один разможет потеряться
At-least-onceсообщение доставится минимум один разможет обработаться дважды
Exactly-onceсообщение обработается ровно один разсамая сложная и дорогая гарантия
Копнуть глубже

At-least-once — самая частая гарантия на практике. Consumer подтверждает (commit) offset после успешной обработки сообщения — если он упадёт между обработкой и подтверждением, при перезапуске обработает это же сообщение заново. Это безопаснее, чем потерять сообщение, но требует, чтобы обработка была идемпотентной (см. тему «Идемпотентность и безопасность методов») — повторная обработка не должна приводить к двойному эффекту (например, двойному списанию денег).

Как добиться идемпотентности на практике — обычно через уникальный id сообщения/операции, который проверяется перед обработкой:

void processPayment(PaymentEvent event) {
    if (paymentRepository.existsById(event.getId())) {
        return;   // уже обработали — пропускаем повтор
    }
    // реальная обработка платежа
}

Exactly-once в Kafka технически возможен (через транзакционный producer + идемпотентный producer), но добавляет существенные накладные расходы и сложность настройки — на практике большинство систем выбирают at-least-once + идемпотентность на стороне обработчика, это даёт тот же практический эффект проще и дешевле.

🎤 Закрыл тему, если можешь объяснить:
• три вида гарантий доставки и их риски;
• почему at-least-once требует идемпотентной обработки на стороне consumer'а (если дошёл до 3-го слоя).