Хабрахабр

[Перевод] Apache Kafka и RabbitMQ: семантика и гарантия доставки сообщений

В этой публикации речь идёт о семантике и гарантии доставки сообщений. Подготовили перевод следующей части многосерийной статьи, где сравнивается функциональность Apache Kafka и RabbitMQ. 10 включительно, а в версии 0. Обращаем ваше внимание, что автор учитывал Кафку до версии 0. Тем не менее, статья остаётся актуальной и полна полезных с практической точки зрения моментов.
Предыдущие части: первая, вторая.
И RabbitMQ, и Kafka предлагают надёжные гарантии доставки сообщений. 11 появился exactly-once. Обе платформы предлагают гарантии по принципам “как максимум однократная доставка” и “как минимум однократная доставка”, но вот с принципом “строго однократной доставки” гарантии Kafka действуют по очень ограниченному сценарию.

Сперва разберёмся, что означают эти гарантии:

  • At-most-once delivery (“как максимум однократная доставка”). Это значит, что сообщение не может быть доставлено больше одного раза. При этом сообщение может быть потеряно.
  • At-least-once delivery (“как минимум однократная доставка”). Это значит, что сообщение никогда не будет потеряно. При этом сообщение может быть доставлено более одного раза.
  • Exactly-once delivery (“строго однократная доставка”). Святой грааль систем сообщений. Все сообщения доставляются строго единожды.

Слово “доставка” здесь, вероятно, будет не совсем точным термином. Точнее было бы сказать “обработка”. Во всяком случае, интересует нас сейчас то, может ли потребитель обрабатывать сообщения и по какому принципу это происходит: “не более одного”, “не менее одного” или “строго единожды”. Но слово “обработка” усложняет восприятие, и выражение “Доставка по принципу ‘строго единожды’” в данном случае будет недостаточно точным определением, потому что может потребоваться доставить сообщение дважды, чтобы должным образом обработать его один раз. Если получатель отключился во время обработки, требуется, чтобы сообщение было отправлено вторично новому получателю.

Обсуждая вопрос обработки сообщений, мы подходим к теме частичных отказов, являющейся головной болью для разработчиков. Второе. Он состоит из сеансов связи между приложением и системой сообщений в начале и в конце и работы самого приложения с данными в середине. В процессе обработки сообщения присутствует несколько этапов. Если выполняемые операции полностью транзакционны и результаты формулируются по принципу “всё или ничего”, частичных сбоев в логике приложения удаётся избежать. Сценарии частичных отказов в работе приложения должны обрабатываться самим приложением. Если мы включаем во взаимодействие взаимосвязи между системами обмена сообщениями, приложениями, кэшем и базой данных, можем ли мы гарантировать обработку по принципу “строго единожды”? Но нередко многие этапы включают в себя с взаимодействие с другими системами, где транзакционность невозможна. Ответ — “нет”.

По этому ограниченному сценарию можно обрабатывать сообщения, писать их, отправлять сигналы о том, что они обработаны в рамках транзакции, производимой по принципу “всё или ничего”. Стратегия “строго единожды” ограничена сценарием, по которому единственным получателем обработанных сообщений является сама платформа обмена сообщениями, и сама эта платформа обеспечивает полноценные транзакции. Это предусмотрено библиотекой Kafka Streams.

Если конечная обработка сообщений идемпотентна, можно не беспокоясь принимать дубликаты. Но если обработка сообщений всегда идемпотентна, можно избежать необходимости реализовывать стратегию “строго единожды” через транзакции. Но не все действия можно реализовать идемпотентно.

Сквозное оповещение

Если учесть, что в RabbitMQ сообщение может быть поставлено в несколько очередей, сквозное оповещение не имеет смысла. Что не представлено ни в каких устройствах всех систем обмена сообщениями, с которыми я работал, так это сквозное подтверждение. По моему опыту, сквозное оповещение — это то, о чём чаще всего просят люди, плохо знакомые с концепцией передачи сообщений. На Kafka, аналогично, несколько разных групп получателей могут считывать информацию одновременно из одного топика. В таких случаях лучше сразу объяснять, что это невозможно.

Цепочка ответственности

Они могут только знать, что система обмена сообщениями приняла их сообщения и взяла на себя ответственность по обеспечению их безопасного хранения и доставки. По большому счёту, источники сообщений не могут знать, что их сообщения доставляются получателям. Каждый должен корректно выполнять свои обязанности и четко передавать сообщение следующему. Возникает цепочка ответственности, которая начинается источником, идёт по системе обмена сообщениями и заканчивается на получателе. Это значит, что вы как разработчик должны грамотно спроектировать свои приложения, чтобы не допустить утери или некорректного использования сообщений, пока они у вас под контролем.

Порядок передачи сообщений

Но есть ещё порядок передачи сообщений. Эта статья посвящена, прежде всего, тому, как каждая платформа обеспечивает отправку по стратегиям “не менее одного” и “не более одного”. В предыдущих частях этой серии я писал о порядке передачи сообщений и порядке их обработки и я советую обратиться к этим частям.

RabbitMQ поддерживает такой порядок на уровне очереди, а Kafka — на уровне распределения на сегменты. Если коротко, то и RabbitMQ, и Kafka предоставляют гарантию порядка простой очерёдности (first in first out, FIFO). Последствия таких проектных решений были рассмотрены в предыдущих статьях.

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

Гарантии доставки обеспечиваются:

  • надежностью сообщений — они не пропадут, пока хранятся на RabbitMQ;
  • уведомлениями о сообщениях — RabbitMQ обменивается сигналами с отправителями и получателями.

Элементы, обеспечивающие надежность

Зеркалирование очереди

Для каждой очереди предусмотрена ведущая очередь на одном из узлов. Очереди могут быть зеркалированы (реплицированы) на многих узлах (серверах). 10 контрольных очередей и 20 реплик будет распределено по трём узлам. Например, есть три узла, 10 очередей и по две реплики на очередь. В случае зависания узла: Распределение контрольных очередей по узлам может быть настроено.

  • вместо каждой ведущей очереди на зависшем узле предоставляется реплика этой очереди на другом узле;
  • на других узлах создаются новые реплики, чтобы заменить потерянные реплики на выбывшем узле, таким образом поддерживая фактор реплицирования.

Речь об устойчивости к сбоям пойдёт в следующей части статьи.

Надёжные очереди

Надёжные очереди записываются на диск и сохраняются в случае перезагрузки узла. На RabbitMQ предусмотрено два типа очередей: надёжные и ненадёжные. При запуске узла они переопределяются.

Устойчивые сообщения

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

Если имеется поток событий реального времени и не критично потерять несколько из них или небольшой временной промежуток потока, лучше не применять реплицирование очередей и передавать все сообщения как неустойчивые. При работе на RabbitMQ, чем надёжней сообщения, тем ниже возможная производительность. Но если терять сообщения из-за сбоя в работе узла нежелательно, лучше применять надёжные очереди с реплицированием и устойчивые сообщения.

Уведомления о получении сообщений

Передача сообщений

Это зависит от поведения отправителя. Сообщения могут быть утеряны или дублированы при передаче.

“Выстрелил и забыл”

Сообщения не будут дублироваться, но могут потеряться (что удовлетворяет стратегии “как максимум однократная доставка”). Источник может решить не запрашивать от получателя подтверждения (уведомления о получении сообщения для отправителя) и просто отправить сообщение в автоматическом режиме.

Подтверждения отправителю

Теперь в ответ на полученное сообщение брокер очередей должен предоставить одно из двух: Когда отправитель открывает канал для брокера очередей, он может использовать этот же канал для передачи подтверждений.

  • basic.ack. Положительное подтверждение. Сообщение получено, ответственность за него теперь лежит на RabbitMQ;
  • basic.nack. Негативное подтверждение. Что-то случилось, и сообщение не было обработано. Ответственность за него остаётся на источнике. При желании, он может отправить сообщение вторично.

В дополнение к положительным и отрицательным уведомлениям о доставке сообщения предусмотрено сообщение basic.return. Иногда отправителю нужно знать не только о том, что сообщение поступило в RabbitMQ, но и о том, что оно действительно попало в одну или несколько очередей. Может так получиться, что источник отправляет сообщение в систему распределения по очередям (topic exchange), в которой сообщение не маршрутизируется в ни одну из очередей доставки. В такой ситуации брокер просто отбрасывает сообщение. В одних сценариях это нормально, в других же источник должен знать, было ли сообщение сброшено, и действовать дальше в соответствии с этим. Можно выставить флаг “Mandatory” для отдельных сообщений, и, если сообщение не было определено в какую-либо очередь доставки, отправителю будет возвращено сообщение basic.return.

Вместо этого источники могут высылать стабильный поток сообщений, задав для себя ограничение на количество неподтверждённых сообщений. Источник может дожидаться подтверждения после отправки каждого сообщения, но это сильно снизит производительность его работы. Когда будет достигнут промежуточный предел сообщений, отправка будет приостановлена, пока не будут получены все подтверждения.

Всем сообщениям, отправляемым по каналу, присваивается монотонно возрастающее целое значение, “порядковый номер” (Sequence Number). Теперь, когда имеется множество сообщений, находящихся в пути от отправителя к RabbitMQ, для повышения производительности группируются подтверждения, используя флаг multiple. И если при этом значение multiple=true, отправитель должен отслеживать порядковые номера своих сообщений, чтобы знать, какие сообщения были успешно доставлены, а какие нет. Уведомление о поступлении сообщения включает порядковый номер соответствующего сообщения. Я написал подробную статью на эту тему.

Благодаря подтверждениям мы избегаем потерь сообщений следующими способами:

  • переотправка сообщений в случае поступления негативного уведомления;
  • продолжение хранения сообщений где-нибудь в случае получения негативного уведомления или basic.return.

Транзакции.

Транзакции редко используются в RabbitMQ по следующим причинам:

  • Слабые гарантии. Если сообщения направляются на несколько очередей или имеют значок об обязательности, неразрывность транзакций не будет поддержана;
  • Низкая производительность.

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

Ошибки средств коммуникации/каналов

Оба эти фактора приводят к потере канала связи. Помимо уведомлений о получении сообщений, отправителю нужно иметь в виду сбои средств коммуникации и брокеров. Здесь отправитель должен выбрать между риском потери сообщений и риском их дублирования. С потерей каналов пропадает возможность получить любые ещё не доставленные уведомления о получении сообщений.

Или, возможно, сообщение было определено в очередь, но брокер сообщений умер перед тем, как отправить подтверждение. Сбой брокера может произойти, когда сообщение было в буфере операционной системы или проходило предобработку, и тогда сообщение будет потеряно. В этом случае сообщение будет успешно доставлено.

Произошел ли сбой во время передачи сообщения? Аналогично влияет на ситуацию сбой средств коммуникации. Или же после того, как сообщение было поставлено в очередь, но до получения положительного уведомления?

Отправителю невозможно это определить, поэтому он должен выбрать один из следующих вариантов:

  • не переотправлять сообщение, создавая риск его утери;
  • переотправлять сообщение и создать риск его дублирования.

Если многие сообщения отправителя находятся в пути, проблема усложняется. Единственное, что отправитель может сделать — это дать получателям подсказку, добавив специальный заголовок к сообщению, показывающий, что сообщение отправляется вторично. Получатели могут принять решения о том, чтобы проверять сообщения на наличие подобных заголовков и в случае обнаружения таковых дополнительно проверять полученные сообщения на наличия дубликатов (если такая проверка ранее не проводилась).

Получатели

Получателям доступны две опции, регулирующие уведомления о получении:

  • режим отсутствия уведомлений;
  • ручной режим уведомлений.

Режим отсутствия уведомлений

И он опасен. Он же режим автоматических уведомлений. Это может привести к потере сообщения, если: Прежде всего потому, что, когда сообщение попадает в ваше приложение, оно удаляется из очереди.

  • соединение прервалось до момента получения сообщения;
  • сообщение всё ещё во внутреннем буфере, а приложение отключили;
  • не удалось произвести обработку сообщения.

К тому же, мы теряем механизмы противодавления как средство контроля качества доставки сообщений. Установив режим отправки уведомлений вручную, можно задать предвыборку (или установить уровень предоставляемых услуг, QoS), чтобы ограничить единовременное количество сообщений, получение которых система ещё не подтвердила. Без этого RabbitMQ отправляет сообщения настолько быстро, насколько позволяет соединение, а это может быть быстрее, чем получатель способен их обработать. В результате буферы переполняются, и возникают ошибки памяти.

Ручной режим уведомлений

Он может установить предвыборку на случай, если количество сообщений больше одного, и обрабатывать много сообщений одновременно. Получатель должен вручную отправить уведомление о получении каждого сообщения. Группировка уведомлений повышает производительность. Он может решить отправлять по уведомлению на каждое сообщение, а может применить флаг multiple и высылать по нескольку уведомлений одновременно.

Оно включается в каждое уведомление о получении и используется как идентификатор сообщения. Когда получатель открывает канал, сообщения, идущие по нему, содержат параметр Delivery Tag, значения которого представляет собой целое, монотонно возрастающее число.

Уведомления могут быть следующие:

  • basic.ack. После него RabbitMQ удаляет сообщение из очереди. Здесь может быть применён флаг multiple.
  • basic.nack. Получатель обязан установить флаг, чтобы сообщить RabbitMQ, ставить ли сообщение заново в очередь. При повторной постановке сообщение попадает в начало очереди. Оттуда оно отправляется получателю опять (даже тому же получателю). Уведомление basic.nack поддерживает флаг multiple.
  • basic.reject. То же, что и basic.nack, только не поддерживает флаг multiple.

Таким образом, семантически basic.ack и basic.nack при requeue=false одинаковы. Оба оператора означают удаление сообщения из очереди.

Если сообщение было обработано быстро, возможно, сразу после завершения этой операции (удачной или неудачной) вы захотите отправить уведомление. Следующий вопрос заключается в том, когда отправлять уведомления о получении. Отправка уведомления после этого будет проблематична, потому что, если канал закроется, все сообщения, на которые не было уведомлений, вернутся в очередь, и отправка будет произведена вторично. Но если сообщение стояло в очереди RabbitMQ и на обработку уходит много минут?

Ошибка соединения/брокера сообщений

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

Когда сообщение отправляется повторно, RabbitMQ для флага переотправки устанавливает значение “true”. Чем дольше у получателя долгое время имеются сообщения, получение которых он не подтвердил, тем выше риск переотправки. Благодаря этому получатель по крайней мере имеет индикацию того, что сообщение, возможно, уже было обработано.

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

Если проверка на дублирование сообщений слишком дорога, можно применить стратегию, при которой отправитель всегда добавляет специальный заголовок на повторно отправляемые сообщения, а получатель проверяет полученные сообщения на наличие такого заголовка и флага повторной отправки. Если требуется идемпотентность и гарантии того, что ни одно сообщение не будет потеряно, следует встроить какую-нибудь проверку дубликатов или другие идемпотентные схемы.

Заключение

RabbitMQ предоставляет надёжные, долговременные гарантии обмена сообщениями, но есть много ситуаций, когда они не помогут.

Вот список моментов, которые следует запомнить:

  • Следует применять зеркалирование очередей, надёжные очереди, устойчивые сообщения, подтверждения для отправителя, флаг подтверждения и принудительное уведомление от получателя, если требуются надёжные гарантии в стратегии “как минимум однократная доставка”.
  • Если отправка производится в рамках стратегии “как минимум однократная доставка”, может потребоваться добавить механизм дедубликации или идемпотентности при дублировании отправляемых данных.
  • Если вопрос потери сообщений не так важен, как вопрос скорости доставки и высокой масштабируемости, то подумайте о системах без резервирования, без устойчивых сообщений и без подтверждений на стороне источника. Я всё же предпочел бы оставить принудительные уведомления от получателя, чтобы контролировать поток принимаемых сообщений путем изменения ограничений предвыборки. При этом вам потребуется отправлять уведомления пакетами и использовать флаг “multiple”.

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

Гарантии доставки обеспечиваются:

  • долговечностью сообщений — сообщения, сохранённые в сегменте, не теряются;
  • Уведомлениями о сообщениях — обмен сигналами между Kafka (и, возможно, хранилищем Apache Zookeeper) с одной стороны и источником/получателем — с другой.

Два слова о пакетировании сообщений

Одно из отличий RabbitMQ от Kafka заключается в использовании пакетов при обмене сообщениями.

RabbitMQ обеспечивает что-то похожее на пакетирование благодаря:

  • Приостановке отправки каждые Х сообщений до тех пор, пока не будут получены все уведомления. RabbitMQ обычно группирует уведомления, используя флаг «multiple».
  • Установке получателями параметра «prefetch» и группировкой уведомлений с помощью «multiple».

Но всё же сообщения не отправляются пакетами. Это больше похоже на непрерывный поток сообщений и отправку групп уведомлений в одном сообщении при отмеченном значке “multiple”. Как это делает протокол TCP.

Пакетирование делается ради производительности, но иногда возникает необходимость в компромиссе между производительностью и другими факторами. Kafka обеспечивает более явное пакетирование сообщений. Чем больше сообщений было в пути в момент сбоя, тем больше возникает дублей и происходит повторной обработки сообщений. Аналогичная ситуация возникает в RabbitMQ, когда сдерживающим фактором становится количество сообщений, которые ещё в пути, уведомлений о поступлении которых ещё нет.

Каждый раздел закреплён за одним получателем, поэтому даже применение больших пакетов не влияет на распределение работы. Kafka более эффективно работает с пакетами со стороны получателя, потому что работа распределяется по разделам, а не по конкурирующим получателям. RabbitMQ по своему устройству не подходит для пакетной обработки сообщений. Но если вместе с RabbitMQ используется устаревший API для считывания больших пакетов, это может привести к крайне неравномерной нагрузке между конфликтующими между собой получателями и значительным задержкам в обработке данных.

Элементы, обеспечивающие устойчивость

Репликация журнала

Лидер каждого сегмента может иметь несколько ведомых. Для защиты от сбоев у Kafka предусмотрена архитектура ведущий-ведомый на уровне раздела журнала, и в этой архитектуре ведущие называются лидерами, а ведомые еще могут называться репликами. Если на сервере, где находится лидер, происходит сбой, предполагается, что реплика становится лидером и все сообщения сохраняются, только обслуживание на короткое время прерывается.

Каждая реплика может быть или не быть в синхронизированном состоянии. Kafka придерживается концепции синхронизации реплик (In Sync Replicas, ISR). Она выпадает из синхронизации, если не успевает эти сообщения принять. В первом случае она получает те же сообщения, что и лидер, за короткий отрезок времени (обычно за последние 10 секунд). Потеря сообщений может произойти только в случае сбоя лидера и отсутствия участвующих в синхронизации реплик. Такое может произойти из-за сетевой задержки, проблем с виртуальной машиной узла и т.д. Я расскажу об этом подробнее в следующей части.

Уведомления о получении сообщений и отслеживание смещения

Учитывая то, как Kafka хранит сообщения, и то, как они доставляются получателям, Kafka полагается на уведомления о получении сообщений для источников и отслеживание смещения чтения топика для получателей.

Уведомление о получении сообщения для источника

Когда источник посылает сообщение, он даёт знать брокеру Kafka, какого рода уведомление он хочет получить, задав одну из настроек:

  • Без уведомлений, автоматический режим. Acks=0.
  • Уведомление о получении сообщения лидером. Acks=1
  • Уведомление о получении сообщения лидером и всеми участвующими в синхронизации репликами. Acks=All

Сообщения могут быть дублированы при отправке по тем же причинам, что и в RabbitMQ. В случае сбоя брокера или сети во время отправки, отправителю придётся ещё раз выслать сообщения, уведомления о принятии которых он не получил (если он не хочет, чтобы они были потеряны). Но вполне возможно, что это сообщение или сообщения были уже получены и среплицированы.

Для её работы должны быть соблюдены следующие условия: Однако у Kafka предусмотрена хорошая опция против проблем с дублированием.

  • для enable.idempotence установлено значение “true”,
  • для max.in.flight.requests.per.connection установлено значение 5 или менее,
  • для retries установлено значение 1 или выше,
  • для acks установлено значение “all”.

Следовательно, при пакетной отправке шести или более сообщений или если acks=0/1 для повышения производительности, данная опция не может использоваться.

Отслеживание смещения получателем

Эти данные могут быть сохранены в ZooKeeper или другом топике Kafka. Получатели должны сохранять смещение своего последнего полученного сообщения, чтобы в случае сбоя новый получатель мог продолжить с того места, где остановился предыдущий.

Когда получатель считывает пакеты сообщений из раздела (топика), у него есть несколько вариантов относительно того, когда сохранять смещение своего последнего полученного сообщения:

  • Периодически. По мере обработки сообщений клиентская библиотека контролирует периодические фиксации смещения. Это делает работу со смещениями очень простой с точки зрения программиста и также положительно влияет на производительность. Но такой подход повышает риск повторной доставки при сбое получателя. Получатель может успеть обработать пакет сообщений и упасть прежде, чем он успеет зафиксировать соответствующее смещение.
  • Немедленно, перед началом обработки сообщений. Это соответствует стратегии отправки сообщений “как максимум однократная доставка”. При этом не важно, когда могли быть сбои у получателя; сообщение не будет обработано дважды, но может остаться необработанным. Например, если 10 сообщений обрабатывались и на пятом у получателя произошёл сбой, обработанными окажутся только 4 сообщения, остальные будут сброшены, и следующий получатель начнёт с сообщений, которые поступят после этого пакета;
  • В конце, когда все сообщения обработаны. Это соответствует стратегии отправки сообщений “как минимум однократная доставка”. Не важно, когда могли быть сбои у получателя, ни одно сообщение не останется необработанным, но одно и то же сообщение может быть обработано несколько раз. Например, если 10 сообщений обрабатывались и на пятом у получателя произошёл сбой, все десять сообщений будут считаны следующим получателем, и 4 сообщения окажутся обработаны дважды;
  • Поочередно. Это сократит возможность дублирования, но сильно снизит производительность работы.

Стратегия “строго однократная доставка” ограничена Kafka Streams, клиентской библиотекой от Java. При использовании Java настоятельно рекомендую обратить внимание на неё. При использовании стратегии “строго однократная доставка”, главная сложность будет заключаться в том, что и обработка сообщения, и сохранение смещения последнего полученного сообщения должно производиться в одной транзакции. Например, если обработка сообщения предполагает отправку сообщения по электронной почте, сделать это в рамках стратегии “строго однократная доставка” не получится. Если после отправки электронного письма у получателя произошёл сбой до того, как он сохранил смещение последнего полученного сообщения, новый получатель (сообщения) должен будет снова отправить это письмо.

Это обеспечивается с помощью транзакционной функциональности Kafka: отправить сообщение в другой топик и записать смещение можно в рамках одной транзакции. Приложения, использующие Kafka Streams, у которой последнее действие по обработке сообщения заключается в том, чтобы записать новое сообщение в другой топик, могут действовать в рамках стратегии “строго однократная доставка”. Вне зависимости от того, когда произойдет сбой получателя, и запись смещения, и запись в топик либо будут выполнены (и только один раз), либо нет одновременно. Обе операции будут успешны, или обе будут неудачны.

О транзакциях и уровнях изоляции

В транзакции могут участвовать сразу несколько топиков и разделов. Главным сценарием применения транзакций в Kafka является упомянутый выше сценарий “чтение-обработка-написание”. Отправитель начинает транзакцию, создаёт пакет сообщений, завершает транзакцию.

Если получатели используют изоляционный уровень “чтение зафиксированного”, они не видят сообщения, транзакции которых не завершены или отменены. Если получатели используют по умолчанию изоляционный уровень “читать незафиксированное”, они видят все сообщения, независимо от их транзакционного статуса (завершена, не завершена, отменена). Они могут принимать сообщения только завершенных транзакций.

Он не влияет никак. Может возникнуть вопрос: как изоляционный уровень “чтение завершенных транзакций” влияет на гарантии порядка отправки сообщений? Незавершенные транзакции будут блокировать чтение. Получатели будут считывать все сообщения в нужном порядке, это прекратится на первом сообщении, транзакция которого не завершена. Смещение последней завершенной транзакции (Last Stable Offset, LSO) — это смещение до первой незавершенной транзакции; получатели с уровнем изоляции “чтение завершенных транзакций” могут читать только до данного смещения.

Выводы

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

Подведём итоги

  • Обе платформы способны реализовать стратегии “как максимум однократная доставка” и “как минимум однократная доставка”.
  • Обе платформы обеспечивают репликацию сообщений.
  • На обеих платформах действуют одинаковые факторы, в силу которых следует искать компромисс между пропускной способностью системы и риском дублирования сообщений. Kafka обеспечивает идемпотентную отправку сообщений, но только для ограниченного объёма трафика.
  • Обе платформы задают ограничения количества передаваемых сообщений, находящихся в пути, подтверждение о получении которых ещё не получено отправителем.
  • Обе платформы предоставляют гарантии относительно порядка отправки сообщений.
  • Kafka обеспечивает поддержку транзакций, в первую очередь в сценарии “чтение-обработка-написание”. При этом нужно принять меры против снижения пропускной способности системы.
  • В Kafka, если получатель не обрабатывает часть сообщений из-за сбоев техники и некорректного отслеживания смещения последнего полученного сообщения, все равно можно восстановить смещение этого сообщения (если такой случай обнаружен). В RabbitMQ соответствующие сообщения будут утеряны.
  • Kafka может повысить пользу от пакетирования благодаря своим возможностям по распределению пакетов, а в RabbitMQ пакетирование отсутствует в силу пассивной модели приёма, не препятствующей конфликтам получателей.
Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»