#redis #rabbitmq #publish-subscribe #messaging
#redis #rabbitmq #опубликовать-подписаться #обмен сообщениями
Вопрос:
Требование
Система претерпевает некоторое изменение состояния, и об этом должны знать несколько других частей системы (назовем их наблюдателями), чтобы они могли выполнять некоторые действия на основе текущего состояния, действия наблюдателей важны, если некоторые наблюдатели не подключены к Сети (в настоящее время не прослушиваются из-за некоторыхпроблема, но скоро вернется), сообщение не следует отбрасывать, пока все наблюдатели не получат сообщение.
Пытаясь выполнить это с помощью модели pub / sub, вот мои выводы (пожалуйста, исправьте, если это понимание неверно) —
Издатель создает событие по определенной теме, и несколько подписчиков могут использовать одно и то же сообщение. Эта модель либо не предоставляет гарантии доставки (в redis), либо доставка гарантируется один раз (с очередями обмена сообщениями), т.е. когда один из потребителей подтверждает сообщение, сообщение отбрасывается (rabbitmq).
Пример
В БД создается новый объект профиля пользователя
Теперь,
- Служба фоновой проверки должна знать это, чтобы запустить процесс проверки.
- Служба подписок должна знать это, чтобы добавить подписки по умолчанию для пользователя.
Теперь обе задачи важны, не связаны и могут выполняться параллельно.
Теперь в модели очереди, если служба подписки по какой-либо причине отключена, процесс проверки BG подтверждает сообщение, сообщение будет удалено из очереди, или, если оно запущено и забыто, как и большинство pub / sub, доставка в любом случае не гарантируется для обеих служб.
Еще один момент — обе задачи не связаны и не должны запускаться одна за другой.
Короче говоря, мне нужно убедиться, что все потребители получают одно и то же сообщение, и они должны иметь возможность подтверждать их по отдельности, сообщение должно быть удалено только после того, как все потребители признали это, ни один из вышеперечисленных подходов этого не делает.
Чего-нибудь мне здесь не хватает? Как мне подойти к этой проблеме?
Ответ №1:
Этот сценарий явно поддерживается моделью RabbitMQ, которая отделяет «обмены» от «очередей»:
- Издатель всегда отправляет сообщение на «exchange», который является просто адресом маршрутизации без сохранения состояния; ему не нужно знать, в какие очереди должно попасть сообщение
- Потребитель всегда считывает сообщения из «очереди», которая содержит свою собственную копию сообщений, независимо от того, откуда они возникли
- Несколько потребителей могут подписаться на одну и ту же очередь, и каждое сообщение будет доставлено только одному потребителю
- Важно отметить, что обмен может направлять одно и то же сообщение в несколько очередей, и каждая получит копию сообщения
Здесь важно понять, что, хотя мы говорим о потребителях, «подписывающихся» на очередь, частью «подписки» в настройке «pub-sub» на самом деле является маршрутизация из exchange в очередь.
Таким образом, система RabbitMQ pub-sub может выглядеть следующим образом:
- В БД создается новый объект профиля пользователя
- Это событие публикуется как сообщение в разделе «события» exchange с ключом маршрутизации «entity.profile.created»
- Обмен направляет копии сообщения в несколько очередей:
- К этому обмену была привязана очередь «verification_service» для получения копии всех сообщений, соответствующих «entity.profile.#»
- К этому обмену была привязана очередь «subscription_setup_service» для получения копии всех сообщений, соответствующих «entity.profile.created»
- Сценарии-потребители ничего не знают об этой маршрутизации, они просто знают, что сообщения будут появляться в очереди для событий, которые имеют отношение к ним:
- Служба проверки получает копию сообщения в очереди «verification_service», обрабатывает и подтверждает ее
- Служба настройки подписки получает копию сообщения в очереди «subscription_setup_service», обрабатывает и подтверждает его
- Если есть несколько сценариев-пользователей, просматривающих одну и ту же очередь, они будут делиться сообщениями в этой очереди между собой, но при этом полностью независимы от любой другой очереди.
Вот скриншот из этого интерактивного инструмента визуализации, который показывает этот сценарий:
Комментарии:
1. Большое вам спасибо, ваш ответ четко отвечает всем пунктам моего вопроса. Два сомнения — 1) Происходит ли привязка потребителя к их отдельной очереди по умолчанию? Если это так, то как биржа узнает о привязке — 1queue: несколько потребителей (например, очередь заданий, кто бы ни был свободен, получите задачу, подтвердите и удалите задание из очереди) против 1queue: один потребитель. Какие-либо явные конфигурации? 2) Является ли эта модель уникальной для rabbitmq или других поставщиков большинства очередей, достигающих этого тем или иным способом?
2. @YuvarajG Существует две привязки: несколько очередей могут быть привязаны к exchange, и каждая получает копию сообщения, предоставляя функциональность «pub-sub»; затем несколько потребителей могут привязаться к одной из этих очередей и будут получать сообщения, распределяемые между ними, создавая «рабочий пул» функциональность. Эти два набора привязок полностью независимы — обмен ничего не знает о потребителях, а потребитель ничего не знает об обменах. Честно говоря, я мало что знаю о других очередях сообщений и о том, как работает их маршрутизация, поэтому не могу ответить на эту часть.
3. На сайте RabbitMQ есть много документации и руководств, которые стоит прочитать. Вы также можете найти игру с этим инструментом полезной для визуализации процесса: tryrabbitmq.com
Ответ №2:
Как вы упомянули, это не то, что вы можете контролировать с помощью структуры данных Redis Pub / Sub.
Но вы можете сделать это легко с помощью потоков Redis.
Потоки позволят вам отправлять сообщения с помощью XADD
команды, а затем контролировать, какие потребители имеют дело с сообщением, и подтверждать, что сообщение было обработано.
Вы можете посмотреть на эти примеры приложений, которые предоставляют (на Java) пример о:
- отправка и использование сообщений
- создайте несколько групп потребителей
- управление исключениями
Ссылки:
- Начало работы с потоками Redis и Java
- Потоки Redis в действии ( проект, который показывает, как использовать ADD / ACK / PENDING / CLAIM и создавать потоковое приложение с защитой от ошибок с помощью потоков Redis и SpringData)
Комментарии:
1. Спасибо за ответ, я уже пробовал потоки redis раньше, я полагаю, что группы потребителей в Redis предназначены для использования разных частей сообщения в одной теме разными группами потребителей, поэтому group1 не использует и не подтверждает часть сообщения, которая совпадает с group2, верно? Но мне нужно, чтобы потребители получали свою собственную копию полного сообщения и подтверждали то же самое. И я не хочу дублировать сообщения, создавая новые очереди для каждого потребителя.