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 ...
随机推荐
- IE下页面左偏移并页头空出一行解决方法
在其它浏览器下显示正常,包括360浏览器,在IE下,页面向左偏移,通过firebug查看,head标签为空,并且head标签里面的内容都跑到body标签内了,原因是有bom头,访问的页面或是加载,包含 ...
- Oracle作业5——多表查询、子查询
一.基础练习: 1.查询和scott相同部门的员工姓名ename和雇用日期hiredate SELECT ENAME,HIREDATE FROM EMP WHERE DEPTNO=(SELECT DE ...
- 工具 | Axure基础操作 No.1
Axure作为一款热门的原型设计工具,是产品汪必备的一个技能.对于我个人来说,虽然更加喜欢墨刀这种小清新并且易用的网页版轻量级工具. 我在这里进行一些简单操作的动图,方便和我一样刚入门的同学容易看得明 ...
- Swift_错误处理
Swift_错误处理 点击查看源码 //错误处理 func test() { //错误枚举 需ErrorType协议 enum ErrorEnum: Error { case `default` // ...
- Magazine Ad CodeForces - 803D(二分 + 贪心,第一次写博客)
Magazine Ad The main city magazine offers its readers an opportunity to publish their ads. The forma ...
- 557. Reverse Words in a String III (5月25日)
解答 class Solution { public: string reverseWords(string s) { string temp,result; while(1){ if(s.find( ...
- 学习笔记 - 2sat
学习笔记 - 2sat 决定重新启用Markdown--只是因为它支持MathJax数学公式 noip考完,既轻松又无奈,回来慢慢填坑 这篇博客也是拖了好久,通过kuangbin的博客才弄懂2-sat ...
- Linux下Git远程仓库的使用详解
Git远程仓库Github 提示:Github网站作为远程代码仓库时的操作和本地代码仓库一样的,只是仓库位置不同而已! 准备Git源代码仓库 https://github.com/ 准备经理的文件 D ...
- python开发的学生管理系统
python开发的学生管理系统(基础版) #定义一个函数,显示可以使用的功能列表给用户 def showInfo(): print("-"*30) print(" 学生管 ...
- sql查询关于时间的一些汇总
今天的所有数据:select * from 表名 where DateDiff(dd,datetime类型字段,getdate())=0 昨天的所有数据:select * from 表名 where ...