php多进程单例模式下的 MySQL及Redis连接错误修复
前几天写了个php常驻脚本,主要逻辑如下
//跑完数据后休息60秒
$sleepTime = 60;
$maxWorker = 10;
while (true) {
    $htmlModel = new DetailHtmlModel();
    //新抓取的html数目
    $count = $htmlModel->getCount(array(
        array('status', '=', DetailHtmlModel::STATUS_UNDEAL)
    ));
    if ($count > 0) {
        //将抓取的html数据放入队列
        Queue::putHtmlData();
    }
    $queueLength = Queue::getHtmlQueueLength();
    if ($queueLength > 0) {
        //启动的worker数目,限制启动的个数
        $workerCount = min($maxWorker, ceil($queueLength / 10));
        runWorker($workerCount);
        $sleepTime = 60;
    } else {
        //无数据的话每次多停5秒
        $sleepTime += 5;
    }
    unset($htmlModel);
    sleep($sleepTime);
}
看代码知道,我根据待处理的数据量启动最多10个的worker去处理数据,每个worker是一个进程,但跑起来后遇到两个错误: 
一个是mysql的:MySQL server has gone away 
另一个是redis的:Uncaught exception ‘RedisException’ with message ‘read error on connection’
原因:
出现MySQL server has gone away 常见的原因就是连接时间超过了mysql设置的wait_timeout值,这时mysql会主动关掉连接,默认是8小时。但是我是启动脚本就出现这个错误,而且使用连接前都先做了ping,不可能是连接超时了,又看了mysql官网对这个错误可能原因的说明(原文)里面有这么一句:
You can also encounter this error with applications that fork child processes, all of which try to use the same connection to the MySQL server. This can be avoided by using a separate connection for each child process.
很多公司代码在创建mysql和redis的连接实例时,采用的都是单例模式,我们也一样。也就是说无论外部new了多少实例,只要句柄存在就会被返回,而不是重新创建连接实例。刚好我又启动了多个进程去处理数据,然后每个进程又使用同一个连接实例,就导致了报错
解决办法:
通常只有在cli运行模式下才有可能出现超时的情况,所以在构建mysql单例句柄的key时使用getmypid()加入进程id,这样就能把每个进程使用的连接实例分隔开 
mysql:
private static function _getHandleKey($params) {
    //解决多进程会保持同一个连接的错误
    if (PHP_SAPI === 'cli') {
       $params['pid'] = getmypid();
    }
    ksort($params);
    return md5(implode('_' , $params));
}
redis也使用同样方法解决问题
php多进程单例模式下的 MySQL及Redis连接错误修复的更多相关文章
- redis连接错误3种解决方案System Error MISCONF Redis is configured to save RDB snapshots
		
redis连接错误System Error MISCONF Redis is configured to save RDB snapshots, but XX 情况1解决办法: 由于强制停止red ...
 - Linux下开启MySQL的远程连接
		
今天在用客户端工具远程连接mysql的时候,连接不上,以为是防火墙,关了防火墙后依然打不开,后开在网上查了下原来mysql基于安全考虑root账户一般只能本地访问,但是在开发过程中可能需要打开root ...
 - windows linux 下安装mysql 报1045 等错误
		
曾经在windows 下安装mysql 没怎么出现过问题.而在linux下安装的时候出现了一些问题,昨天在windows 安装的时候也出现了1045 错误.就个人经历来看这个问题就是 root用户pa ...
 - linux搭建的LNMP环境下的mysql授权远程连接
		
用phpstudy搭建的lnmp环境下mysql授权远程连接 简单高效 这是因为mysql 里的优先级不是所有人(提前检查防火墙是关闭状态)1.使用phpstudy安装的mysql没有放置到可以直接调 ...
 - Linux CentOs 下 安装 mysql nginx redis
		
SCP 的使用 来源于: https://blog.csdn.net/qq_30968657/article/details/72912070 scp [参数] <源地址(用户名@IP地址或主机 ...
 - linux下遇见mysql启动报2002错误解决办法
		
前言:目前问题解决了,但是仍不知道是什么原因造成的,在出现问题前安装uWSGI后,mysql就出现这个问题的,哪位大侠说说这是怎么回事? 正文:Linux 下 Mysql error 2002 错误解 ...
 - 亚马逊EC2 ubuntu下安装mysql远程无法连接问题o
		
无法远程的原因有很多,我今天遇到的问题是通过navicat无法远程连接我在EC2上创建的实例. 1.通过命令" netstat -an|grep 3306 "检查一下3306端口对 ...
 - CentOS下WDCP下的MYSQL开启远程连接
		
1.首先要在防火墙开启3306端口访问 2.然后做如下操作 如何开启MySQL的远程帐号-1)首先以 root 帐户登陆 MySQL 在 Windows 主机中点击开始菜单,运行,输入"cm ...
 - Linux下设置mysql允许远程连接
		
最近在Linux上安装了Mysql,然后在Windows环境下通过Navicat来连接时,出现报错:1045 Access denied for user 'root'@'XXX' (using pa ...
 
随机推荐
- 关于sharepoint如何做SSO,如何做OOS监视编辑
			
应客户需求,需要做sharepoint SSO,以前都是默认的AD验证,如果客户已经有一套SSO系统,验证过SSO之后就能自动登录,而不是浏览器上设置保存用户名密码的AD登陆. 怎么做呢? 首先sha ...
 - vue移动端项目vw适配运行项目时出现"advanced"报错解决办法。
			
Module build failed: Error: Cannot load preset "advanced". Please check your configuration ...
 - ABAP术语-SAPNET
			
SAPNET 原文:http://www.cnblogs.com/qiangsheng/archive/2008/03/17/1109823.html SAPNet is the intranet p ...
 - 原生JS实现移动端的轮播效果
			
首先 我们想实现的效果是在手指按下拖动的时候图片能够跟随移动(无动画效果)然后松开手指后判断图片移动的位置 和某一个值进行比较 在这里我们默认定为盒子的1/3宽度 当x轴的移动位置大于1/3的时候图片 ...
 - hql返回数值
			
public int getCountUser() throws ParseException { Session hSession = sessionFactory.getCurrentSessio ...
 - go加密算法:CBC对称加密(一)--DES
			
package main import ( "bytes" //"crypto/aes" "crypto/cipher" "cry ...
 - 【Spark】源码分析之RDD的生成及stage的切分
			
一.概述 Spark源码整体的逻辑(spark1.3.1): 从saveAsTextFile()方法入手 -->saveAsTextFile() --> saveAsHadoopFile ...
 - JAVA 中的文件读取
			
1. InputStream / OutputStream处理字节流抽象类:所有输入.输出(内存)类的超类,一般使用 FileInputStream / FileOutputStream 输出字符 u ...
 - Struts2+EasyUI+Hibernate小实例
			
概述 这个实例主要是前台数据到后台数据的传递和后台数据到前台数据的传递,完成数据的新增,以及对新增数据的展示.下面是详细的过程: Hibernate(数据库部分) 这里只是数据库的连接和数据库实体与物 ...
 - Ubuntu Linux TinySerial串口调试助手 可视化界面 安装使用
			
ubuntu Linux下串口调试助手使用 Tiny Serial为一个开源项目,欢迎大家使用,基于Qt开发的串口调试助手,有一般串口助手的基本功能,更多功能正在完善. Github地址:https: ...