php之redis短线重连案例讲解
作者:flysnownet 发布时间:2023-06-12 13:16:04
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


猜你喜欢
- 数独规则数独游戏,经典的为9×9=81个单元格组成的九宫格,同时也形成了3×3=9个小九宫格,要求在81个小单元格中填入数字1~9,并且数字
- 这篇文章主要介绍了python已协程方式处理任务实现过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的
- 一般来说一个系统最先出现瓶颈的点很可能是数据库。比如我们的生产系统并发量很高在跑一段时间后,数据库中某些表的数据量会越来越大。海量的数据会严
- 一:js原型继承四步曲//js模拟类的创建以及继承 //动物(Animal),有头这个属性,eat方法 //名字这个属性 //猫有名字属性,
- 本文实例讲述了Python使用Dijkstra算法实现求解图中最短路径距离问题。分享给大家供大家参考,具体如下:这里继续前面一篇《Pytho
- Pandas最初被作为金融数据分析工具而开发出来,因此,pandas为时间序列分析提供了很好的支持。Pandas的名称来自于面板数据(pan
- 本文实例为大家分享了vue-Split实现面板分割的具体代码,供大家参考,具体内容如下<template> <
- asp连接mysql的问题ASP连接Mysql数据库的问题。下了一个MySql 的ODBC驱动。做了个小测试。顺利通过。先记录下来,中间还有
- 前言本文主要介绍属性、事件和插槽这三个vue基础概念、使用方法及其容易被忽略的一些重要细节。如果你阅读别人写的组件,也可以从这三个部分展开,
- 需要安装OpenCV和SimpleItk。SimpleItk比较简单,直接pip install SimpleItk即可。代码如下:#cod
- 今天在写PHP程序的时候总是出现这样的错误:Parse error: syntax error, unexpected end of fil
- 本文将介绍8个简洁的Python技巧,若非经验十足的程序员,你肯定有些从未见过。向着更简洁更高效,出发吧!1.通过多个键值将对象进行排序 假
- SQL Server中事务日志的作用:持续记录数据库所有的事务和这些事务对数据库所做的修改;一旦数据库出现灾难事件,就需要事务日志来进行近期
- 想必大家都知道MSSQL中SA权限是什么,可以说是至高无上。今天我就它的危害再谈点儿,我所讲的是配合NBSI上传功能得到WebShell。在
- 复制代码 代码如下: public partial class CMS_DBDataContext { partial void OnCre
- vue跳转后不记录历史记录vue路由跳转一般情况下是使用push, this.$router.push({  
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&
- 1、将css与javascript全部用下边的方法分离到外部文件中去。<link rel="stylesheet"
- Python的sys模块提供访问解释器使用或维护的变量,和与解释器进行交互的函数。通俗来讲,sys模块负责程序与python解释器的交互,提
- 前言临近期末做了一个商品销售管理系统,分享下,全部源码在码云,需要自取,博客只分享部分代码(太多了)。数据库的建立我们使用Navicat P