为什么在phpredis连接函数中Try/Catch无法正常工作?

8

我正在使用phpredis将redis作为缓存存储。它运行得非常完美,我想提供一些故障转移的方式,以确保缓存功能始终可用(例如使用基于文件的缓存),即使redis服务器宕机。最初,我想到了以下代码:

<?php
    $redis=new Redis();
    try {
        $redis->connect('127.0.0.1', 6379);
    } catch (Exception $e) {
        // tried changing to RedisException, didn't work either
        // insert codes that'll deal with situations when connection to the redis server is not good
        die( "Cannot connect to redis server:".$e->getMessage() );
    }
    $redis->setex('somekey', 60, 'some value');

但是当 Redis 服务器宕机时,我会收到以下信息:
    PHP Fatal error:  Uncaught exception 'RedisException' with message 'Redis server went away' in /var/www/2.php:10
Stack trace:
#0 /var/www/2.php(10): Redis->setex('somekey', 60, 'some value')
#1 {main}
  thrown in /var/www/2.php on line 10

代码中catch块没有被执行。我回去阅读了phpredis文档,提出了以下解决方案。

<?php
    $redis=new Redis();
    $connected= $redis->connect('127.0.0.1', 6379);
    if(!$connected) {
        // some other code to handle connection problem
        die( "Cannot connect to redis server.\n" );
    }
    $redis->setex('somekey', 60, 'some value');

我可以接受这个结果,但是我的好奇心永远无法得到满足,所以我有一个问题:为什么 try/catch 方法在连接错误时不起作用?

1
$redis->connect(); 如果连接失败,不会抛出异常。你可以检查 $redis===true,如果为真则表示已连接,否则表示未连接。但正如 Nicolas 在下面指出的,上面的异常是来自 setex,因此除非将其放在 try catch 块中,否则无法捕获。 - Haluk
1
@haluk Redis连接方法抛出了一个异常。 - guy_fawkes
4个回答

4

您的异常是来自于setex,而该代码位于try{}块之外。将setex放在try块内部即可捕获该异常。


我认为他期望捕获有关服务不可用的异常,以及命令格式错误的异常。 - Niloct
1
@Niloct,你读懂了我的心思:D确实如果在调用connect()时能够捕获异常会很好。 - ricochen

2

正如Nicolas所说,异常来自于setex,但是您可以通过使用ping命令来避免这种情况(甚至不需要try/catch块):

$redis=new Redis();
$redis->connect('127.0.0.1', 6379);

if(!$redis->ping())
{
    die( "Cannot connect to redis server.\n" );
}

$redis->setex('somekey', 60, 'some value');

6
谢谢你的回答,但我不明白为什么使用额外的命令(如你回答中的ping)比直接检查connect()的结果更好,因为这正是我在代码中实际使用的。 - ricochen

0

我曾经也遇到同样的问题,幸运的是,在这里 https://github.com/phpredis/phpredis/issues/1641 我找到了解决方案。

<?php
$obj_r = new Redis();

$port = isset($argv[1]) ? $argv[1] : 6379;
echo "Attempting to connect to port $port: ";

try {
    $obj_r->connect('127.0.0.1', $port);
} catch(RedisException $ex) {
    $m = $ex->getMessage();
    echo "ERROR ($m)\n";
}

if ($obj_r->isConnected()) {
    echo "OK\n";
    echo "PING -> " . $obj_r->ping() . "\n";
} else {
    // some other code to handle connection problem
    echo "Not connected, can't send PING!\n";
}
?>

0

如果你捕获 '\Predis\Connection\ConnectionException',它可以捕获连接异常。

或者,你可以使用 \Exception 而不是 Exception(注意前面的斜杠)。


这是不正确的。你提到的异常 \Predis\Connection\ConnectionException 是由 Predis客户端 抛出的,而不是 phpredis - Nicolas Favre-Felix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接