PHP网络编程-进程控制篇(二)
发表@2019-11-25 09:40:00
更新@2023-03-26 15:22:52
我先不说为什么,咱先把上面代码xue微修改一下:
```php
connect( '127.0.0.1', 6379 );
// 使用for循环搞出3个子进程来
for ( $i = 1; $i <= 3; $i++ ) {
$i_pid = pcntl_fork();
if ( 0 == $i_pid ) {
// 使用while保证三个子进程不会退出...
while( true ) {
sleep( 1 );
}
}
}
// 使用while保证主进程不会退出...
while( true ) {
sleep( 1 );
}
```
我贴下截图你们感受一下,我相信你们应该能看明白这个图是啥意思...

也就是说父进程和三个子进程一共四个进程,实际上共享了一个Redis连接,而且这个Redis连接是一个实打实的长链接,这个和我们平时在PHP-FPM里用的Redis connect方法还是xue微不一样的,这种长链接避免了与Redis服务器的频繁连接(说百了就是没有三次握手和四次挥手),这种看起来似乎并不起眼的零星性能差距,将会在并发越高的时候越能甩开PHP-FPM短连接一条街...
再回到这个问题当前是四个进程共享了同一个Redis连接,这种用法会有问题么?考虑到Redis是一个单进程单线程的服务器,所有飞过去的命令本质上都是按照顺序一个一个执行的,所以似乎听起来好像没问题...我们把上面代码改一小下下,你们用心去感受一下:
```php
connect( '127.0.0.1', 6379 );
// 使用for循环搞出3个子进程来
for ( $i = 1; $i <= 4; $i++ ) {
$i_pid = pcntl_fork();
if ( 0 == $i_pid ) {
$b_ret = $o_redis->sismember( "uid", $i );
echo $i.':'.json_encode( $b_ret ).PHP_EOL;
// 使用while保证三个子进程不会退出...
while( true ) {
sleep( 1 );
}
}
}
// 使用while保证主进程不会退出...
while( true ) {
sleep( 1 );
}
```
同时,我在Redis里整了一个set集合,名称叫做uid,值为[ 1, 2, 3, 5, 6 ],注意没有4!运行结果真的是... ...

来来来,我连续运行了好多次,你们感受下:

很明显这种用法暴露了两个问题:
- 数字4是确实不会存在uid集合中的,但是有两次结果都是true
- 理论上应该有四条bool结果,结果有时候却只返回三条bool结果
多个进程复用同一个Redis连接,Redis的返回结果永远无法判断会被哪个进程给处理掉了,所以正确的用法应该是给每一个进程分别创建一个Redis连接,代码修改成下面这样就可以了:
```php
connect( '127.0.0.1', 6379 );
$b_ret = $o_redis->sismember( "uid", $i );
echo $i.':'.json_encode( $b_ret ).PHP_EOL;
// 使用while保证三个子进程不会退出...
while( true ) {
sleep( 1 );
}
}
}
// 使用while保证主进程不会退出...
while( true ) {
sleep( 1 );
}
```
这坨代码你们自己去测试执行吧,我就不贴运行结果了,不过我贴一张Redis连接数量的图:

四个子进程,四个与Redis的连接。
所以,如果你要用MySQL,道理也是一样的,同样也会是长链接,同样也是多进程不要共享同一个MySQL连接。
你们以为到这里就算完了吗?不,并没有,我还有一个问题,那就是file_put_contents()...我写了下面一坨代码,你们感受一下并猜测一下使用多个进程利用file_put_contents()函数向同一个文件里写数据,会出问题吗?
```php
>](https://ti-node.com/thread/view/6528965533792993280 "<<老李大战PHP之file_put_contents>>")