PHP Nginx MySQL 高并发调优 小试
程序员文章站
2022-05-21 16:38:12
...
项目要求实现一个免费抢券的功能,涉及到高并发的问题,研究了几天,记录下来,欢迎工友们扔砖头~~
这种方法的缺点在于使用了两次数据库连接,中间插入了PHP判断,必定会造成性能上的损失,好处是数据库不必插入业务逻辑,松耦合。
整个项目是PHP+Nginx+Mysql的架构,由于PHP是阻塞的单线程模型,不支持多线程,因此也没有Java那么好用的同步机制,我想到的办法就是在数据库级别做相应的同步互斥的控制,Mysql的锁机制我放在了Mysql数据库锁机制这篇博文当中。通过查看Mysql官方文档,我想到了两种解决方案:一、使用LOCK TABLE 或START TRANSACTION 写SQL 语句; 二、使用CREATE PROCEDURE 直接在数据库中创建存储过程,接下来我就分别试了这两种方法。
一、 使用锁机制
SET autocommit=0;LOCK TABLE test;select count(*) from test where value=1;COMMIT;这是 查询当天中奖的用户(为了示意简化了业务逻辑),然后我用PHP做一个判断:是否中奖用户超过了当天的限额,没超过则该用户中奖,那么此时要UPDATE 一下数据库,若两个用户同时读取中奖用户总数,其中一个update了数据库,另一个用户读到的自然是脏数据,这也就是为什么我没有释放刚才那张表的锁,按照业务逻辑,是要跳出mysql用程序判断一下,然后update数据库再释放锁。
update test(name,value) values('Tomcat',1);COMMIT;UNLOCK TABLE;
这种方法的缺点在于使用了两次数据库连接,中间插入了PHP判断,必定会造成性能上的损失,好处是数据库不必插入业务逻辑,松耦合。
二、 使用存储过程
DELIMITER //DROP PROCEDURE IF EXISTS proc;CREATE PROCEDURE proc(IN cnt INT,IN user VARCHAR(32))BEGIN DECLARE num INT; DECLARE success INT; select count(*) INTO num from test where value=1; IF num
稍微解释一下代码(熟悉的工友请pass):1. 将mysql默认的分隔符分号重定义为// 避免mysql 只执行其中一句话;2. 创建存储过程传入参数cnt (中奖用户限额), user (此次抢票的用户); 3. 定义两个临时变量num (目前中奖用户数), success(是否中奖);4.查询当前中奖用户数目,未超额则插入用户状态1,反之0 ; 5. 返回中奖与否标志,恢复mysql的sql分隔符.在php中调用此存储过程: $db->query("call proc(100,'hehe')");
此方法的缺点是在数据库引入了业务逻辑,程序修改不易,优点是只使用一次数据库连接,表的锁定时间大大减少,并发效率很高。
三、 奇葩windows环境下的PHP
在我满怀欣喜的开始模拟高并发用户访问的时候,问题来了。。。
先贴 java 写的多线程并发访问程序(php不支持多线程。。)
import java.util.concurrent.CyclicBarrier;import com.test.run.ThreadTest;public class Test { public static void main(String[] args) { CyclicBarrier cb=new CyclicBarrier(100); //fork 100个线程 ThreadTest[] ttarray=new ThreadTest[100]; //待这些线程fork完毕,同时发起http请求 for (int i = 0; i
上一篇: apache服务器首度访问慢
推荐阅读
-
nginx + php(fpm) 提高并发性调优实战
-
PHP Nginx MySQL 高并发调优 小试
-
大并发高负载下的PHP-FPM参数调优
-
php, nginx, apache, mysql PHP如何解决网站大流量与高并发" />
-
php, nginx, apache, mysql PHP如何解决网站大流量与高并发" />