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

到此这篇关于php之redis短线重连案例讲解的文章就介绍到这了,更多相关php之redis短线重连内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • PHP操作Redis常用命令的实例详解

    redis常用命令有: 1.连接操作命令: 2.持久化命令: 3.远程服务控制命令: 4.对value操作命令:5.string命令: 6.list命令: 7.set命令: 8.hash命令等等. Redis 常用命令 登录 redis-cli -p 5566 -a password 检查key是否存在 EXISTS key 搜索某关键字 KSYS *4 返回一个Key所影响的vsl的类型 TYPE key 下面通过代码看下PHP操作Redis命令,代码如下所示: //连接本地的 Redis 服

  • 详解PHP解决守护进程Redis假死

    目录 一.一个简单的守护进程示例 二.一个不再假死(伪活)的 Redis 常驻进程示例 一.一个简单的守护进程示例 <?php $redis = new \Redis(); $redis->connect('localhost', 6379); $redis->auth('xxxxx'); // Redis 密码如果没有设置为空字符串. $redis->select(1); $queueKey = 'redis_queue_services_key'; // 业务数据队列. $qu

  • php基于redis的分布式锁实例详解

    在使用分布式锁进行互斥资源访问时候,我们很多方案是采用redis的实现. 固然,redis的单节点锁在极端情况也是有问题的,假设你的业务允许偶尔的失效,使用单节点的redis锁方案就足够了,简单而且效率高. redis锁失效的情况: 客户端1从master节点获取了锁 master宕机了,存储锁的key还没来得及同步到slave节点上 slave升级为master 客户端2从新的master上获取到同一个资源的锁 于是,客户端1和客户端2同事持有了同一个资源的锁,锁的安全性被打破. 如果我们不考

  • PHP使用Redis队列执行定时任务实例讲解

    Redis类: <?php namespace Utils; use Phalcon\Config\Adapter\Ini as ConfigIni; class Redis{ private static $redis1; private static $session; /** * 获取一个单例的redis对象 * @param string $name * @return \Redis */ public static function getObj($name='redis1') { t

  • php操作redis命令及代码实例大全

    官方PHP Redis扩展文件下载 https://pecl.php.net/package/redis 选择与你PHP版本相应的文件下载后直接放到PHP目录下的ext文件夹里,然后修改php.ini配置文件如下 php.ini文件添加:extension=php_redis.dll 重启php, phpinfo可以看到redis则证明安装成功 php连接redis测试 <?php $redis = new Redis(); $redis->connect('127.0.0.1', 6379)

  • thinkphp5redis缓存新增方法实例讲解

    找到该文件 thinkphp/library/think/cache/driver/Redis.php 进行新增方法 在这里 我就举例几个 如何添加 添加的方法查看 redis教程 /** * 返回列表中指定区间内的元素 * */ public function lrange($key,$start,$end){ return $this->handler->lrange($key,$start,$end); } /** * 在list左边新增元素 * */ public function l

  • php在linux环境中如何使用redis详解

    1.php安装. 2.下载redis并编译(最好是在 /usr/local目录下运行该命令) # wget http://download.redis.io/releases/redis-6.0.8.tar.gz # tar xzf redis-6.0.8.tar.gz # cd redis-6.0.8 # make 3.完成后进入src目录运行redis # cd src # ./redis-server 如果运行成功,会出现redis图片,以及必要信息提示成功. 服务器规则组打开6379端口

  • Thinkphp5+Redis实现商品秒杀代码实例讲解

    环境:wamp,redis 要求:安装WAMP,Redis,以及为PHP安装Redis扩展 秒杀功能大致思路:获取缓存列表的长度,如果长度(llen)等于0,就停止秒杀,即秒杀失败,如果长度大于0,则继续运行,先从缓存中移除一个元素(lpop),再进行数据库操作(添加订单表,商品库存数量减一),如果再进一个人秒杀,就再走一遍流程,循环往复. 一.安装Redis扩展 1.查看PHP版本信息 打开phpinfo.php,查看PHP版本,我的是PHP7.3.4,还有一个需要注意Architecture

  • 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实例时,如果pin

  • Java之理解Redis回收算法LRU案例讲解

    如何通俗易懂的理解LRU算法? 1.LRU是什么? LRU全称Least Recently Used,也就是最近最少使用的意思,是一种内存管理算法,最早应用于Linux操作系统. LRU算法基于一种假设:长期不被使用的数据,在未来被用到的几率也不大.因此,当数据所占内存达到一定阈值时,我们要移除掉最近最少被使用的数据. LRU算法应用:可以在内存不够时,从哈希表移除一部分很少访问的用户. LRU是什么?按照英文的直接原义就是Least Recently Used,最近最久未使用法,它是按照一个非

  • Redis之windows下主从复制案例讲解

    一般的主从复制功能最少是一主二从,我这里就以最低要求进行配置. 1.首先下去官网下载并安装redis 若安装成功点击redis-server  如此是成功 2.点击客户端redis-cli 连接客户端即可使用 3.新建7000.7001两个从redis  4.修改redis-windows.conf   (1)把端口修改成7000 (2)修改cluster-config-file的名字 以免和6379端口的名字重复其他配置默认即可,我个人认为我们都重新建了一个文件夹也不可能出现和6379重复的错

  • SpringBoot集成SSM、Dubbo、Redis、JSP的案例小结及思路讲解

    1.思路讲解 这个案例其实就是SpringBoot集成SSM.Dubbo.Redis.JSP,看起来集成了一大堆,感觉挺麻烦的,但实际上并不是很麻烦,下面我来说一下我的思路: 接口工程:存放实体bean和业务接口 服务提供者:它是一个SpringBoot框架web项目,集成MyBatis.Redis 1)pom文件中添加依赖:MyBatis.MySQL驱动.Dubbo.zookeeper.redis.接口工程. 2)配置springboot核心配置文件(连接数据库.连接redis.dubbo.内

  • Java之操作Redis案例讲解

    首先 下载 jedis.jar包 然后再 工程设置里面找到Libraries,点击+.添加下载好的jedis.jar包.点击OK退出即可 创建Java_Control_Redis类 测试链接 package ccit.redis; import redis.clients.jedis.Jedis; public class Java_Control_Redis { public static void main(String[] args) { //连接本地的 Redis 服务 Jedis je

  • php之使用docker运行workerman案例讲解

    介绍 在docker上部署gatawayWorker项目,项目中使用到mysql,redis 安装 mysql 拉取镜像 docker pull mysql:5.7 运行容器 docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root --name m_mysql mysql:5.7 -d 后台运行 -p 端口映射,前面是宿主机端口,后面是需要映射的容器端口 -e 设置环境变量,MYSQL_ROOT_PASSWORD是mysql的root用户的初

  • java volatile案例讲解

    本篇来自java并发编程实战关于volatile的总结. 要说volatile,先得明白内存可见性.那我们就从内存可见性说起. 一.内存可见性 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.在单线程环境中,如果向某个变量先写入值,然后在没有其他写入操作的情况下读取这个变量,那么总能得到相同的值.这看起来很自然.然而,当读操作和写操作在不同的线程中执行时,情况却并非如此,这听起来或许有些难以接受.通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有时甚至是根本不可能

  • MySQL之权限以及设计数据库案例讲解

    权限及设计数据库 用户管理 使用SQLyog 创建用户,并授予权限演示 基本命令 /* 用户和权限管理 */ ------------------ 用户信息表:mysql.user -- 刷新权限 FLUSH PRIVILEGES -- 增加用户 CREATE USER kuangshen IDENTIFIED BY '123456' CREATE USER 用户名 IDENTIFIED BY [PASSWORD] 密码(字符串) - 必须拥有mysql数据库的全局CREATE USER权限,或

  • 案例讲解WEB 漏洞-文件操作之文件下载读取

    目录 原理 漏洞危害 利用方式 系统文件 window Linux 常见脚本敏感文件参考 任意文件读取 任意文件下载 Google search 漏洞利用代码 漏洞挖掘 漏洞验证 漏洞防范 案例 pikuchu靶场-文件下载测试 小米路由器-文件读取真实测试-漏洞 RoarCTF2019-文件读取真题复现 百度杯2017二月-Zone真题复现 原理 产生:任意语言代码下载函数 文件下载(一些网站由于业务需求,往往需要提供文件查看或文件下载功能,但若对用户查看或下载的文件不做限制,则恶意用户就能够

  • C语言深入探究选择排序与基数排序使用案例讲解

    目录 一.选择排序 1.1 选择排序引入 1.2 选择排序的基本思想与算法分析 1.3 实例说明 1.4 代码实现 1.5 性能分析 二.基数排序 2.1 基数排序基本思想与算法步骤 2.2 实例说明 2.3 代码实现 2.4 性能分析 一.选择排序 1.1 选择排序引入 就像炒股一样,有的人爱炒短线,不断的买进卖出通过差价来盈利,但是频繁的买进卖出,也会因为频繁的手续费和一系列费用获益较少:有的人,不断的进行观察和判断,等到时机一到,果断买进或卖出,这种人交易次数少,而最终收获颇丰:正如我们所

随机推荐