2014-01-07 82 views
1

我正在尝试使用Redis构建消息队列。 每当客户端发送新数据时,它们都会添加到列表中。使用redis实现消息队列时出错,使用BLPOP时出错

这里是它的代码

$client->lPush("my_queue", $data); 

现在有一个单独的脚本slave.php,弹出新接收数据并对其进行处理。 为slave.php

while (true) { 
    list($queue, $message) = $client->brPop(["my_queue"], 0); 

    /* 
    Logic to process the data 
    */ 
} 

我已经修改Apache的启动脚本,使slave.php应该开始&停止与Apache代码。它运作良好。但是,等待几分钟后brPop停止,像这样的错误消息监听:

Uncaught exception 'Predis\Connection\ConnectionException' with message 'Error while reading line from the server [tcp://127.0.0.1:6379]' in /var/www/api/lib/predis-0.8/lib/Predis/Connection/AbstractConnection.php:139 
Stack trace: 
#0 /var/www/api/lib/predis-0.8/lib/Predis/Connection/StreamConnection.php(205): Predis\Connection\AbstractConnection->onConnectionError('Error while rea...') 
#1 /var/www/api/lib/predis-0.8/lib/Predis/Connection/AbstractConnection.php(128): Predis\Connection\StreamConnection->read() 
#2 /var/www/api/lib/predis-0.8/lib/Predis/Connection/AbstractConnection.php(120): Predis\Connection\AbstractConnection->readResponse(Object(Predis\Command\ListPopLastBlocking)) 
#3 /var/www/api/lib/predis-0.8/lib/Predis/Client.php(227): Predis\Connection\AbstractConnection->executeCommand(Object(Predis\Command\ListPopLastBlocking)) 
#4 /var/www/api/lib/slave.php(7): Predis\Client->__call('brPop', Array) 
#5 /var/www/api/lib/slave.php(7): Predis\Client->brPop(Array, 0) 
#6 {main} 
thrown in /var/www/api/lib/predis-0.8/lib/Predis/Connection/AbstractConnection.php on line 139 

根据该文件,如果列表为空的话,直到另一个客户端BLPOP/BRPOP块连接执行LPUSH或RPUSH操作反对其中一个键。 但是这不是在我的情况发生。 在我的情况下,一旦brpop阻塞连接,即使新数据到达列表中,它也不会再次侦听。

我应该做些什么改变才能使它工作?

+1

我会建议确保两个脚本连接到同一个数据库上的同一个Redis实例。它应该工作。另外,设置无限超时是一种不好的做法。等待10秒钟,处理/忽略代码中的空结果会更好。 –

+0

是的..两个脚本连接到同一个数据库上的同一个redis实例。正如我所提到的,它在几分钟内运作良好。但等待几分钟后,它会阻止连接,并且不会再次收听。关于等待10秒,我们可以这样做,但我认为BLPOP具有一些功能,通过该功能,每当新数据到达列表中时,从脚本都会发现它。同时提出不必要的空请求会增加服务器负载 –

+0

如果每10秒检查一次,则每20或30 * 10亿个周期增加一些额外的指令。这并不重要,但会使您的服务更加可靠。迪迪埃是对的;这是阻止Redis中弹出窗口的非常标准的做法。 – Jimothy

回答

0

它现在为我工作,但我不知道这是否是正确的方法来做到这一点。现在我正在捕获错误并在连接失败的情况下递归调用该函数。我的新slave.php看起来像这样:

function process_data() 
{ 
    try { 
     $client = new \Predis\Client(); 

     require_once("logger.php"); 

     while (true) { 
      list($queue, $message) = $client->brPop(["bookmark_queue"], 0); 
      // logic 
     } 
    } catch (Exception $ex) { 
     $error = $ex->getMessage(); 
     log_error($error, "slave.php"); 
     process_data(); // call the function recursively if connection fails 
    } 
} 
process_data(); // call the function 
+0

这已经超过一年了。你有没有想办法(比如说'$ client'和其他的设置超时)避免'Exception'? –

0

?read_write_timeout=-1添加到您的连接字符串。

+0

也许如果这是简单的答案,不应该删除。我会等待OP批准或降低答案,但仍然看起来很差。人们可以扩大一点解释 –

相关问题