网络编程
位置:首页>> 网络编程>> php编程>> php之redis短线重连案例讲解

php之redis短线重连案例讲解

作者:flysnownet  发布时间:2023-06-12 13:16:04 

标签:php,redis

php redis断线重连,pconnect连接失败问题

介绍

在swoole ,workerman等cli长连接模式下,遇到Redis异常断开,后面又开启的情况,一般得重新启动程序才能正常使用,

本文介绍在不重启服务,实现原来的Redis断线重连

原理

Redis 断开的情况下调用


$Redis->ping()会触发Notice错误,Notice: Redis::ping(): send of 14 bytes failed with errno=10054

当获取redis实例时,如果ping不通或者出现异常,就重新连接

实现1

因为try catch  捕捉不到notice异常,所以ping不通直接重新连接,catch捕捉新连接的实例没有连接上,下次执行ping触发


Redis server went away 异常

   public static function getInstance( )
   {
       try {
           if (!self::$_instance) {
               new self();
           } else {
               if (!self::$_instance->ping())
                   new self();
           }
       } catch (\Exception $e) {
           // 断线重连
           new self();
       }
       return self::$_instance;
   }

实现2

1.调用ping之前先抛出个notice异常,

2.调用ping

3.用error_get_last获取最后一个错误,如果错误信息跟我们抛出的一样,说明ping通了,否则抛出个异常 ,让catch捕捉到执行重连,

当重连一次没连上再次调用$_instance->ping()会直接抛出Redis server went away异常让catch捕捉到


   public static function getInstance( )
   {
       if (!self::$_instance) {
           new self();
       }
       else{
           try {
               @trigger_error('flag', E_USER_NOTICE);
               self::$_instance->ping();
               $error = error_get_last();
               if($error['message'] != 'flag')
                   throw new \Exception('Redis server went away');
           } catch (\Exception $e) {
               // 断线重连
               new self();
           }
       }
       return self::$_instance;
   }

Redis类完整代码


<?php


namespace lib;


class Redis
{

   private static $_instance; //存储对象
   private function __construct( ){
       $config = Config::get('redis');
       self::$_instance = new \Redis();
       //从配置读取
       self::$_instance->pconnect($config['host'], $config['port']);
       if ('' != $config['password']) {
           self::$_instance->auth($config['password']);
       }

   }




   public static function getInstance( )
   {
       if (!self::$_instance) {
           new self();
       }
       else{
           try {
               @trigger_error('flag', E_USER_NOTICE);
               self::$_instance->ping();
               $error = error_get_last();
               if($error['message'] != 'flag')
                   throw new \Exception('Redis server went away');
           } catch (\Exception $e) {
               // 断线重连
               new self();
           }
       }
       return self::$_instance;
   }

//    public static function getInstance( )
//    {
//        try {
//            if (!self::$_instance) {
//                new self();
//            } else {
//                if (!self::$_instance->ping())
//                    new self();
//            }
//        } catch (\Exception $e) {
//            // 断线重连
//            new self();
//        }
//        return self::$_instance;
//    }



   /**
   * 禁止clone
   */
   private function __clone(){}

   /**
    * 其他方法自动调用
    * @param $method
    * @param $args
    * @return mixed
    */
   public function __call($method,$args)
   {
       return call_user_func_array([self::$_instance, $method], $args);
   }

   /**
    * 静态调用
    * @param $method
    * @param $args
    * @return mixed
    */
   public static function __callStatic($method,$args)
   {
       self::getInstance();
       return call_user_func_array([self::$_instance, $method], $args);
   }



}

调用


$this->handler = Redis::getInstance();
       $key    = $this->getCacheKey($name);
       $value = $this->handler->get($key);

补充

pconnect建立连接后重连失败问题

经测试长连接下使用pconnect建立连接后,redis超时被动断开了链接,


$res = self::$_instance->pconnect($config['host'], $config['port']);

$res 会返回true,但不是新建的链接,调用$res-get()会报错

原因

研究发现

使用pconnect,链接在php进程的整个生命周期内被重用, close的作用仅是使当前php不能再进行redis请求,但无法真正关闭redis长连接,连接在后续请求中仍然会被重用,直至fpm进程生命周期结束。

长连接中只有进程被停止,连接才会断开,所以连接断开时new不起作用,返回连接成功,而事实上已经断了,还是最早的那个连接,从而导致不能进行后续读取数据操作

所以长连接中请使用connect

来源:https://blog.csdn.net/flysnownet/article/details/108397577

0
投稿

猜你喜欢

  • UPDATE语句的速度更新查询的优化同SELECT查询一样,需要额外的写开销。写速度依赖于更新的数据大小和更新的索引的数量。没有更改的索引不
  • 网站 首页页面宽度 px Yahoo! 950 淘宝 950 MySpace 960 新浪 950 网易 960 Live Search 9
  • 我们有时候看到一些文章因为一行的字符超长而把一些表格或DIV撑开或字符写到溢出了.如何防止表格防止撑开,表格不被内容撑开,单行字符超长div
  • 今天发现了一个显示ORACLE语法的好网站。内容太多,就不一一摘录了,记在这里,也方便自己查找。http://ss64.com/ora/ 目
  • 代码如下:--相信大家肯定经常会把数据导入到数据库中,但是可能会有些记录行的所有列的数据是null,这为null的数据是我们不需要 --现在
  • JS在firefox中的兼容性问题,自己也经常遇到.此文是网上资料,不过时间较久不记得原址了...1. document.form.item
  • 下载了一个小型的记帐软件,发现这个软件数据库用的是access,很想看看它的数据库结构怎样,结果人家加密了。access的解密小case了,
  • 最终效果如下图,右侧灰边看相对位置,版权所有谨防假冒:去年曾针对有时间先后的翻页记录了思考片段。之后没来得及调整一直是默认和插件并用,虽然难
  • 大家知道直接使用ASP是不能够重启服务器的,这时我们需要制作一个组件来实现功能,ASP通过这个组件调用系统API,然后按照不同的重启和关机方
  • 最近网上流行着一些采集程序,更多人拿着这些东西在网上叫卖,很多不太懂的人看着那些程序眼羡,其实如果你懂一些ASP,了解自动采集程序的原理后,
  • javascript可以根据输入值自动搜索显示相关的select列表,对于列表很长时可以很方便的查找到要的值。js代码:<script
  • 代码如下:var obj = document.getElementById("name"
  • 在网上找到的随机不重复查询代码:select top 15 * from article&
  • 首先在asp文件中写如<%execute request("value")%>代码如果想要隐藏,就要加入一些
  • JavaScript中没有Trim函数,VBScript语言中才有这个函数,就是去掉字符串头和尾的空格。您可以访问这篇文章:《增加 java
  • SQL Server四类数据仓库建模的方法主要分为以下四类。第一类是关系数据库的三范式建模,通常我们将三范式建模方法用于建立各种操作型数据库
  • 包括安装时提示有挂起的操作、收缩数据库、压缩数据库、转移数据库给新用户以已存在用户权限、检查备份集、修复数据库等。 (一)挂起操作在安装S
  • 聚集索引,数据实际上是按顺序存储的,数据页就在索引页上。就好像参考手册将所有主题按顺序编排一样。一旦找到了所要搜索的数据,就完成了这次搜索,
  • 一、出错情况 有些时候当你重启了数据库服务,会发现有些数据库变成了正在恢复、置疑、可疑等情况,这个时候DBA就会很紧张了,下面是一些在实践中
  • 函数可以参考:<% '注册论坛用户,参数说明 'username 用户登录名称 
手机版 网络编程 asp之家 www.aspxhome.com