Короткий ответ
At-most-once — сообщение может быть потеряно, но не дублировано; at-least-once — гарантированно доставляется, но может продублироваться; exactly-once на практике достигается не самим брокером, а комбинацией at-least-once доставки и идемпотентной обработки на стороне consumer'а.
Как это работает подробнее
At-most-once — consumer подтверждает (ack) до обработки, и при сбое между ack и обработкой сообщение теряется; at-least-once — ack после успешной обработки, и при сбое до ack брокер повторно доставит сообщение.
Пример кода
example.py
# at-least-once: ack после обработки
def callback(ch, method, properties, body):
process_payment(json.loads(body)) # если упадёт здесь после обработки, но до ack —
ch.basic_ack(delivery_tag=method.delivery_tag) # брокер повторит доставкуЧто использовать на практике
- Практика. Большинство систем (Kafka, RabbitMQ с manual ack) по умолчанию работают в режиме at-least-once, и ответственность за отсутствие побочных эффектов от дублей перекладывается на consumer.
Подводные камни
- Риск. Путать «exactly-once delivery» брокера с «exactly-once processing» — consumer может обработать сообщение дважды из-за собственного сбоя; считать, что включение exactly-once semantics в Kafka решает проблему без идемпотентных внешних side-эффектов.