资讯专栏INFORMATION COLUMN

php通过共享内存,控制mysql连接数,多进程插入数据(pcnt学习四)

ivyzhang / 729人阅读

摘要:本人前一遍中提到,当进程数过多时,多进程插入数据库表,超过了最大连接数,就会报错,插入就会有失败的情况。这样就可以控制有的连接数不会达到上限,程序不会出现连接数据库失败的情况。多进程耗内存比较严重,下一步打算用多线程来试试。

本人前一遍blog中提到,当进程数过多时,多进程插入mysql数据库表,超过了mysql最大连接数,就会报错,插入就会有失败的情况。想通过进程间通信来控制一下连接数,参考了一些网上的blog
实现了一下,利用共享内存来存放mysql的连接数,当某个进程在获取信号量后,尝试去连接数据库之前,先判断一下,当前的连接数是否超过了预定的阈值,如果没有,就连接数据库,连接成功后,连接数加一,立马释放信号,等操作数据库完毕后,进程再次阻塞,来获取信号,然后把连接数减一,释放信号量后,进程退出。
这样就可以控制有mysql的连接数不会达到上限,程序不会出现连接数据库失败的情况。当然我可以直接少fork一些进程,本人就是觉得要折腾一下。不然进程通信就懵逼了。而且也不会有以下的问题出现。
但是本人实验,fork一万个子进程,虚拟机很容易就挂了。后来该为fork 5000个子进程,插入一百万条数据,模拟的是最原始的插入。虚拟机虽然没有崩, 但是很卡,期间会出现很多僵尸进程,这里有点疑问。
多进程耗内存比较严重,下一步打算用多线程来试试。
ps:要支持Semaphore函数,php在编译安装是要加上如下参数:

--enable-sysvsem
--enable-sysvshm
--enable-sysvmsg

为此,我还重新编译了php。。。。蛋疼啊。代码如下:

 0) {
        //$id = pcntl_wait($status,WNOHANG);
        $child[] = $pid;
    } else if ($pid == 0) {
        while(true) {
            // 获得信号量
            sem_acquire($signal);
            $count = shm_get_var($shm_id, SHARE_KEY);
            if ($count >= $poolSize) {
                sem_release($signal);
                continue;
            } else {
                $link  = mysqli_connect("localhost","root","root","yii2advanced");
                if ($link) {
                    $count++;
                    shm_put_var($shm_id,SHARE_KEY,$count);
                    sem_release($signal);
                    $start = ($i-1)*$per + 1;
                    $end   = $start + $per;
                    for($j = $start; $j< $end; $j++){
                        $time = microtime(true);
                        $sql = "insert pcntl_test (rank,time) values (".$j.",".$time.")";
                        mysqli_query($link,$sql);
                    }
                    mysqli_close($link);
                    break;
                }
                
            }
            sleep(1);
        }
        sem_acquire($signal);
        $count = shm_get_var($shm_id,SHARE_KEY);
        $count--;
        shm_put_var($shm_id, SHARE_KEY, $count);
        sem_release($signal);
        $id = getmypid();
        $count++;
        echo "count : ".$count." child ".$id." finished ".microtime(true).PHP_EOL;
        exit(0);
    
    }
}
while(count($child)){
    foreach($child as $k => $pid) {
        $res = pcntl_waitpid($pid, $status, WNOHANG);
        if ( -1 == $res || $res > 0) {
            unset($child[$k]);
        }
    }
}
$end = microtime(true);
echo "end ".$end.PHP_EOL;
echo "fork ".$num."process insert ".$total." recodes takes ".($end-$begin).PHP_EOL;

最后,我统计分析了一下5千个进程,一百万条记录,插入时,mysql的连接数情况(平均连接数为464),用python作图如下:

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/22717.html

相关文章

  • swoole入门4-初识swoole

    摘要:当某种网络事件发生时,会回调用户设置的指定回调函数。承担了底层网络事件的监听及各种底层事件处理,当收到请求时,会触发事件提醒,然后将控制权转交预先注册的事件回调函数,来进行后续的处理。请求到来时创建,请求结束后销毁。 运行流程图 showImg(https://segmentfault.com/img/remote/1460000017207791);showImg(https://s...

    forsigner 评论0 收藏0
  • php进程插入据(pcntl 学习笔记二)

    摘要:进程切换太多,影响了了效率应该是原因之一。当时,十万条记录,个进程插入总时间为单进程插入万条数据,耗时秒,相对个进程插入万记录来说,耗时少些。而单进程插入万条记录,耗时,相对来说,是挺慢的了。 个人在虚拟机centos7,单核,1G内存 /** * 模拟并发请求,10万次写入数据库 * 拆分为10个进程,每个进程处理一万条插入 */ $total = 10000; $num ...

    CoyPan 评论0 收藏0
  • 深入了解SAPI

    摘要:将环境变量和标准输入发送到子进程子进程完成处理后将标准输出和错误信息从同一连接返回。当子进程关闭连接时,请求便告知处理完成。定义一个子进程最多处理的请求数,达到这个值,进程自动退出。 一、SAPI比较 1. SAPI 服务器应用程序编程接口,就是服务器与编程语言之间交互的接口。比如Linux命令行执行一段PHP代码,其实是Linux shell通过PHP SAPI传入一组参数,zend...

    CoderBear 评论0 收藏0

发表评论

0条评论

ivyzhang

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<