MySQL连接池
在传统的网站开发中,比如LNMP模式,由Nginx的master进程接收请求然后分给多个worker进程,每个worker进程再链接php-fpm的master进程,php-fpm再根据当前情况去调用其worker进程然后处理PHP,如果需要MySQL,在与MySQL建立连接,这个时候,如果有1000个请求打过来,就需要与MySQL建立1000个连接。如果请求达到万级或者百万级,这时数据库的压力就会非常大了。连接池技术就可以派上用场了,可以大大降低数据库连接数,还可以降低IO消耗。
为什么可以降低IO消耗?
MySQL短连接每次请求操作数据库都需要建立与MySQL服务器建立TCP连接,这是需要时间开销的。TCP连接需要3次网络通信。这样就增加了一定的延时和额外的IO消耗。请求结束后会关闭MySQL连接,还会发生3/4次网络通信。
而连接池采用的是MySQL的长连接模式,会一直保持与MySQL的连接,重用连接进行MySQL的操作,从而节省了建立连接和断开连接的消耗。
为什么可以降低数据连接数呢?
据的连接池为维持若干个长连接,当新请求到达的时候,如果连接池空闲,就分配给连接池去处理,否则,后面的数据库连接请求将被加入到等待队列中。
用swoole实现一个简单的MySQL连接池
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | <?php $serv = new swoole_server( '0.0.0.0' , 9509); $serv ->set( array ( 'worker_num' => 50, //worker进程数量 'task_worker_num' => 10, //task进程数量 即为维持的MySQL连接的数量 )); function my_onReceive( $serv , $fd , $from_id , $data ) { echo "收到数据" . $data .PHP_EOL; //taskwait就是投递一条任务,这里直接传递SQL语句了 //然后阻塞等待SQL完成,并返回结果 $result = $serv ->taskwait( $data ); echo "任务结束" .PHP_EOL; if ( $result !== false) { list( $status , $db_res ) = explode ( ':' , $result , 2); if ( $status == 'OK' ) { //数据库操作成功了,执行业务逻辑代码,这里就自动释放掉MySQL连接的占用 //将处理结果发送给客户端 $serv ->send( $fd , var_export(unserialize( $db_res ), true) . "\n" ); } else { $serv ->send( $fd , $db_res ); } return ; } else { $serv ->send( $fd , "Error. Task timeout\n" ); //如果返回的是false,则说明taskwait等待超时,可以设置相应的等待超时时间 } } function my_onTask( $serv , $task_id , $from_id , $sql ) { echo "开始做任务 task id:" . $task_id .PHP_EOL; static $link = null; HELL: if ( $link == null) { $link = @mysqli_connect( "127.0.0.1" , "root" , "passwd" , "database" ); if (! $link ) { $link = null; $serv ->finish( "ER:" . mysqli_error( $link )); return ; } } $result = $link ->query( $sql ); if (! $result ) { //如果查询失败了 if (in_array(mysqli_errno( $link ), [2013, 2006])){ //错误码为2013,或者2006,则重连数据库,重新执行sql $link = null; goto HELL; } else { $serv ->finish( "ER:" . mysqli_error( $link )); return ; } } if (preg_match( "/^select/i" , $sql )){ //如果是select操作,就返回关联数组 $data = $result ->fetch_assoc(); } else { //否则直接返回结果 $data = $result ; } $serv ->finish( "OK:" . serialize( $data )); //调用finish方法,用于在task进程中通知worker进程,投递的任务已完成 //return "OK:".serialize($data); } function my_onFinish( $serv , $task_id , $data ) { echo "任务完成" ; //taskwait 没有触发这个函数。。 echo "AsyncTask Finish:Connect.PID=" . posix_getpid() . PHP_EOL; } $serv ->on( 'receive' , 'my_onReceive' ); $serv ->on( 'task' , 'my_onTask' ); $serv ->on( 'Finish' , 'my_onFinish' ); $serv ->start(); //启动server |
本文来自博客园,作者:孙龙-程序员,转载请注明原文链接:https://www.cnblogs.com/sunlong88/p/9013300.html
分类:
随笔
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能