Почему Redis для очередей?
У меня сложилось впечатление, что Redis может стать хорошим кандидатом для внедрения системы массового обслуживания. До этого момента мы использовали нашу базу данных MySQL с опросом или RabbitMQ. С RabbitMQ у нас было много проблем - клиентские библиотеки очень плохие и глючные, и мы хотели бы не тратить слишком много времени на их исправление, несколько проблем с консолью управления сервером и т. Д. И на время По крайней мере, мы не стремимся к миллисекундам или серьезному увеличению производительности, поэтому, пока система имеет архитектуру, которая интеллектуально поддерживает очередь, мы, вероятно, в хорошей форме.
Хорошо, так что это фон. По сути, у меня есть очень классическая, простая модель очереди - несколько производителей, производящих работу, и несколько потребителей, потребляющих работу, и как производители, так и потребители должны иметь возможность разумного масштабирования. Оказывается, наивный PUBSUB
не работает, так как я не хочу, чтобы все подписчики потребляли работу, я просто хочу, чтобы один подписчик получил работу. На первый взгляд, это выглядит как BRPOPLPUSH
интеллектуальный дизайн.
Можем ли мы использовать BRPOPLPUSH?
Базовый дизайн BRPOPLPUSH
- у вас есть одна рабочая очередь и очередь выполнения. Когда потребитель получает работу, он атомарно помещает элемент в очередь выполнения, а когда он завершает работу, то это LREM
он. Это предотвращает черную работу, если клиенты умирают, и делает мониторинг довольно легким - например, мы можем сказать, есть ли проблема, заставляющая потребителей занимать много времени для выполнения задач, в дополнение к сообщению, если существует большой объем задач.
Это обеспечивает
- работа доставляется ровно одному потребителю
- работа попадает в очередь выполнения, поэтому она не может быть черной дырой, если потребитель
Недостатки
- Мне кажется довольно странным, что лучший дизайн, который я нашел, на самом деле не использует,
PUBSUB
так как именно на этом и сосредоточено большинство постов в блогах об организации очереди над Redis. Поэтому я чувствую, что упускаю что-то очевидное. Единственный способ, который я использую,PUBSUB
не выполняя задачи дважды, - это просто отправить уведомление о том, что работа пришла, что потребители могут затем неблокироватьRPOPLPUSH
. - Невозможно запросить более одного рабочего элемента за раз, что является проблемой производительности. Не очень большой для нашей ситуации, но довольно очевидно, что эта операция не была рассчитана на высокую пропускную способность или эта ситуация
- Короче говоря: я что-то глупо пропускаю?
Также добавляем тег node.js, потому что это язык, с которым я в основном имею дело. Узел может предложить некоторые упрощения в реализации, учитывая его однопоточный и неблокирующий характер, но, кроме того, я использую библиотеку node-redis, и решения должны или могут быть чувствительны к ее сильным и слабым сторонам.