Вопрос

Почему Redis для очередей?

У меня сложилось впечатление, что Redis может стать хорошим кандидатом для реализации системы массового обслуживания.До этого момента мы использовали нашу базу данных MySQL с опросом или RabbitMQ.С RabbitMQ у нас было много проблем - клиентские библиотеки очень плохие и содержат ошибки, и мы не хотели бы тратить слишком много времени разработчиков на их исправление, некоторые проблемы с консолью управления сервером и т. д.И, по крайней мере, на данный момент мы не хватаемся за миллисекунды и серьезно не повышаем производительность, поэтому, пока система имеет архитектуру, которая разумно поддерживает очередь, мы, вероятно, находимся в хорошей форме.

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

Можем ли мы использовать BRPOPLPUSH?

Базовая конструкция с BRPOPLPUSH у вас есть одна рабочая очередь и очередь выполнения.Когда потребитель получает работу, он атомарно помещает элемент в очередь выполнения, а когда он завершает работу, он LREM'сидеть.Это предотвращает блокирование работы в случае смерти клиентов и делает мониторинг довольно простым — например, мы можем определить, есть ли проблема, из-за которой потребителям требуется много времени для выполнения задач, в дополнение к сообщению о большом объеме задач.

Это обеспечивает

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

Недостатки

  • Мне кажется довольно странным, что лучший дизайн, который я нашел, на самом деле не использует PUBSUB поскольку, похоже, именно на этом сосредоточено большинство сообщений в блогах об очередях в Redis.Поэтому я чувствую, что упускаю что-то очевидное.Единственный способ, который я вижу, использовать PUBSUB без двойного выполнения задач — это просто отправить уведомление о поступлении работы, которое потребители затем смогут неблокировать. RPOPLPUSH.
  • Невозможно запросить более одного рабочего элемента одновременно, что, по-видимому, является проблемой производительности.Не такая уж большая цифра для нашей ситуации, но она явно говорит о том, что эта операция не была рассчитана на высокую пропускную способность или такую ​​ситуацию.
  • Суммируя: я пропустил что-нибудь глупое?

Также добавляю тег node.js, потому что это тот язык, с которым я в основном имею дело.Node может предложить некоторые упрощения в реализации, учитывая его однопоточную и неблокирующую природу, но, кроме того, я использую библиотеку node-redis, и решения также должны или могут быть чувствительны к ее сильным и слабым сторонам.

Это было полезно?

Решение

Если вы хотите использовать Redis для очереди сообщений в Node.js и не против использовать для этого модуль, вы можете попробовать РСМК — Простая очередь сообщений Redis для Node.В то время, когда был задан этот вопрос, он не был доступен, но сегодня это жизнеспособный вариант.

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

Видеть:

Другие советы

На данный момент я столкнулся с некоторыми трудностями, которые хотел бы описать здесь.

Как вы обрабатываете логику повторного подключения?

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

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

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

Сейчас я предпочитаю решение Redis PUBSUB + RPOPLPUSH.Это отделяет уведомление о работе от потребления работы, что позволяет нам выделить чистое решение для прослушивания. PUBSUB несет ответственность только за уведомление о работе. Атомная природа RPOPLPUSH отвечает за потребление и делегирует работу только одному потребителю.Сначала это решение казалось излишне сложным по сравнению с блокирующим всплывающим окном, но теперь я вижу, что усложнение было вовсе не лишним;это решало сложную проблему.

Однако это решение не совсем тривиально:

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

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

Таким образом, основная причина выбора использования RabbitMQ вместо Redis — это сценарии сбоев и кластеризация.

Эта статья действительно объясняет это лучше всего, поэтому я просто предоставлю ссылку:

https://aphyr.com/posts/283-jepsen-redis

Redis Sentinel и, в последнее время, кластеризация Redis не способны обрабатывать ряд очень простых сценариев сбоя, что делает его плохим выбором для очереди.

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

Вот пост для кролика:

https://apyr.com/posts/315-jepsen-rabbitmq

Когда вы смотрите на теорию CAP (согласованность, доступность и обработка разделов), вы можете выбрать только 2 из 3.Мы используем RMQ для CP (обработка согласованности и разделов) при загрузке сообщений. Если мы недоступны, это не конец света.Чтобы не терять сообщения, мы используем ignore для обработки разделов, чтобы не терять сообщения.Дубликаты могут быть обработаны, поскольку источник управляет UUID.

Лицензировано под: CC-BY-SA с атрибуция
scroll top