RabbitMQ-порядок доставки сообщений

Мне нужно выбрать нового брокера очередей для моего нового проекта.

на этот раз мне нужна масштабируемая очередь, поддерживающая pub/sub, и сохранение порядка сообщений является обязательным.

читаю Комментарий Алексея: он пишет:

"действительно, мы думаем, что RabbitMQ обеспечивает более сильный порядок, чем Кафка"

Я прочитал раздел заказа сообщений в документах rabbitmq:

"сообщения могут быть возвращены в очередь с помощью методов AMQP та характеристика в повторной постановки параметр (базовый.выздоравливай, Бейсик.отклонить и основной.НЭК), или из-за канала закрытие при удержании неподтвержденных сообщений...С версии 2.7.0 и выше индивидуальные потребители по-прежнему могут наблюдать сообщения из заказать, если очередь имеет несколько подписчиков. Это связано с действиями другие подписчики, которые могут запрашивать сообщения. С точки зрения очереди сообщения всегда хранятся в публикации порядок."

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

считается ли RabbitMQ хорошим решением для упорядоченной очереди сообщений?

4 ответов


Ну, давайте более подробно рассмотрим сценарий, который вы описываете выше. Я думаю, что важно вставить документация непосредственно перед фрагментом в вашем вопросе, чтобы предоставить контекст:

раздел 4.7 спецификации ядра AMQP 0-9-1 объясняет условия, при которых гарантируется заказ: сообщения, опубликованные в один канал, проходящий через один обмен и одну очередь и один исходящий канал будет получен в том же прикажите, чтобы они были отправленный. RabbitMQ предлагает более сильные гарантии с момента выпуска 2.7.0.

сообщения могут быть возвращены в очередь с помощью методов AMQP, которые имеют параметр requeue (basic.выздоравливай, Бейсик.отклонить и основной.НЭК), или из-за закрытия канала при хранении неподтвержденных сообщений. Любой из в этих сценариях сообщения должны быть запрошены в задней части очередь для выпусков RabbitMQ ранее 2.7.0. От выхода в RabbitMQ 2.7.0, сообщения всегда проходят в очередь в порядке публикации,даже при наличии requeueing или закрытия канала. (курсив)

таким образом, ясно, что RabbitMQ, начиная с 2.7.0, делает довольно резкое улучшение по сравнению с оригинальной спецификацией AMQP в отношении порядка сообщений.

с множественными (параллельными) потребителями, заказ обработки нельзя гарантировать.
Третий абзац (вставленный в вопрос) продолжает давать отказ, который я перефразирую: "если у вас есть несколько процессоров в очереди, нет гарантии, что сообщения будут обрабатываться в порядке.- Все, что они говорят, это то, что кролик не может бросить вызов законам математики.

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

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

теперь может произойти одно из двух. (1) первый клиент в линии может пойти назад к голове линии или (2) первое клиент может опередить третьего клиента, заставив кассира перестать работать с третьим клиентом и начать работать с первым. Этот тип упреждающей логики не поддерживается RabbitMQ и любым другим брокером сообщений, о котором я знаю. В любом случае, первый клиент в конечном итоге не получает помощь первым - это делает второй клиент, которому повезло получить хорошего, быстрого кассира с места в карьер. Единственный способ гарантировать клиентам помощь - это помощь одного кассира клиенты по одному, что вызовет серьезные проблемы с обслуживанием клиентов для банка.

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


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


Я думаю, что в этом вопросе есть две вещи, которые не похожи, порядок потребления и порядок обработки.

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

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

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

  • Если под "обработкой" мы подразумеваем, что сообщение Теперь отброшено и полностью завершено, то рассмотрим случай, когда ваше время обработки не линейно, другими словами, обработка одного сообщения занимает больше времени, чем другое, поэтому, если сообщение 3 занимает больше времени, чем ожидалось, то сообщения 4 и 5 могут быть израсходованы и завершить обработку до сообщения 3

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

Если вы хотите обеспечить порядок обработки тут:

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

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

если вы используете несколько потребителей, они будут обрабатывать сообщение с помощью общего ExecutorService. См. также ConnectionFactory.setSharedExecutor(...). Вы можете установить Executors.newSingleThreadExecutor().

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

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

try (Connection connection2 = factory.newConnection();
        Channel channel2 = connection.createChannel()) {
    // publish messages alternating to two different topics
    for (int i = 0; i < messageCount; i++) {
        final String routingKey = i % 2 == 0 ? routingEven : routingOdd;
        channel2.basicPublish(exchange, routingKey, null, ("Hello" + i).getBytes(UTF_8));
    }
}

теперь вы можете получать сообщения от обоих темы на очереди в том же порядке, в котором они были опубликованы:

// declare a queue for the consumer
final String queueName = channel.queueDeclare().getQueue();

// we bind to queue with the two different routingKeys
final String routingEven = "even";
final String routingOdd = "odd";
channel.queueBind(queueName, exchange, routingEven);
channel.queueBind(queueName, exchange, routingOdd);
channel.basicConsume(queueName, true, new DefaultConsumer(channel) { ... });

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

в документации RabbitMQ есть несколько хороших 5-минутных учебников, которые могут быть полезны: https://www.rabbitmq.com/tutorials/tutorial-five-java.html