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

2022-10-11 21:55:57 147 0
魁首哥

当进程数过多时,多进程插入 mysql 数据库表,超过了mysql最大连接数,就会报错,插入就会有失败的情况。想通过进程间通信来控制一下连接数,

实现了一下,利用 共享内存 来存放mysql的连接数,当某个进程在获取 信号量 后,尝试去连接数据库之前,先判断一下,当前的连接数是否超过了预定的阈值,如果没有,就连接数据库,连接成功后,连接数加一,立马释放信号,等操作数据库完毕后,进程再次阻塞,来获取信号,然后把连接数减一,释放信号量后,进程退出。

这样就可以控制有mysql的连接数不会达到上限,程序不会出现连接数据库失败的情况。当然我可以直接少fork一些进程,本人就是觉得要折腾一下。不然进程通信就懵逼了。而且也不会有以下的问题出现。

但是本人实验,fork一万个子进程, 虚拟机 很容易就挂了。后来该为fork 5000个子进程,插入一百万条数据,模拟的是最原始的插入。虚拟机虽然没有崩, 但是很卡,期间会出现很多僵尸进程,这里有点疑问。

多进程耗内存比较严重,下一步打算用多线程来试试。

ps:要支持Semaphore函数,php在编译安装是要加上如下参数:

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

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

数据库连接池 ,size 为500
*
*/
$total = 1000;
$num = 500;
$per = $total/$num;
$poolSize = 500; // 数据库连接池容量
$ sql  = '';
$child = [];
// 共享内存通信
$shm_key = ftok(__FILE__,'t');
$shm_id = shm_attach($shm_key,1024,0655);
const SHARE_KEY = 1;
$pool = [];
// 加入信号量
$sem_id = ftok(__FILE__,'s');
$ signal  = sem_get($sem_id);
// 初始化连接数量,开始的连接数为0
shm_put_var($shm_id, SHARE_KEY,0);
$begin = microtime(true);
echo 'start '.$begin.PHP_EOL;
for($i = 1; $i<= $num; $i++)
{
 $pid = pcntl_fork();
 if($pid == -1) {
 die('fork error');
 }
 if($pid > 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; 

收藏
分享
海报
0 条评论
147
上一篇:php项目拆分rpc选型 下一篇:微软在Visual Studio中深入集成GitHub:支持开源扩展

本站已关闭游客评论,请登录或者注册后再评论吧~

忘记密码?

图形验证码