blpop перестает обрабатывать очередь через некоторое время

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

Код выглядит примерно так:

while ($item = $redis->blpop(array('someQueue', 'anotherQueue'), 3600)) { someFunction(); } 

Если вы видите, что не так много происходит с точки зрения кода, но время от времени очередь начинает нарастать, и рабочий не выталкивает какой-либо элемент из очереди. Установка тайм-аута для blpop совсем не полезна, поскольку мы исходим из того, что проблема связана с соединением клиента redis.

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

  • Кто-нибудь еще когда-либо сталкивался с этим?
  • Что может быть проблемой?
  • Мы делаем что-то неправильно?

Наш вопрос похож на ошибку в реализации очереди сообщений, используя redis, ошибку при использовании BLPOP, но мы не получаем никаких ошибок. Рабочий просто резко останавливается.

Информация

Сервер Redis: 2.8.2

PHP Redis: phpredis

Обновление # 1

Рабочие, которые работали в течение длительного времени, прекратили обработку очереди. После запуска CLIENT LIST мы заметили, что эти рабочие имеют большой простор по сравнению с остальными, а их флаг установлен на N вместо b . Что может быть причиной этого?

Обновление # 2

Проблема была в someFunction() . Был фрагмент кода, из-за которого функция не возвращала контроль, из-за которого клиент долгое время находился на холостом ходу, и, следовательно, флаг «N» при запуске CLIENT LIST .

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

Шаги, чтобы проверить, что происходит:

  1. Подождите, пока один клиент остановится.
  2. Убедитесь, что на самом деле есть элементы в списке с LLEN команды LLEN .
  3. Проверьте с помощью CLIENT LIST что на самом деле есть ваш клиент, выполняющий блокировку (вы увидите имя команды) и проверьте размер ответа, чтобы узнать, является ли это ваш клиент, который фактически не потребляет отвечает.

Случайные замечания:

  1. Redis 2.8.2. слишком старый, рекомендуется обновить его.
  2. У phpredis могут быть ошибки, которые могут вызвать это, если он так же старый, как сервер Redis.

У нас бы другая проблема: если сервер приложений теряет связь с сервером Redis на некоторое время, дескриптор Redis становится недействительным (кстати, мы ожидаем этого – это не ошибка). Хотя ваша проблема другая, работа, которую мы использовали, может работать и на вас:

Вы можете сделать что-то вроде этого:

 while (true) { // The factory method below will check whether handle is valid. If not, create a new one and return $redis = MyRedisFactory::getInstance(); $item = $redis->blpop(array('someQueue', 'anotherQueue'), 3600); someFunction(); }