Rumah > pembangunan bahagian belakang > tutorial php > PHP通过加锁实现并发抢购功能

PHP通过加锁实现并发抢购功能

*文
Lepaskan: 2023-03-18 20:24:01
asal
2486 orang telah melayarinya

本文基于php语言使用加锁实现并发情况下抢购功能,特定时间段开放抢购并不允许开放的码重复。本文介绍的非常详细,需要的朋友参考下。希望对大家有所帮助。

需求:抢码功能

要求:

1、特定时间段才开放抢码;

2、每个时间段放开的码是有限的;

3、每个码不允许重复;

实现:

1、在不考虑并发的情况下实现:

<p style="margin-top: 5px; margin-bottom: 5px;">function get_code($len){<br/>$CHAR_ARR = array(&#39;1&#39;,&#39;2&#39;,&#39;3&#39;,&#39;4&#39;,&#39;5&#39;,&#39;6&#39;,&#39;7&#39;,&#39;8&#39;,&#39;9&#39;,&#39;A&#39;,&#39;B&#39;,&#39;C&#39;,&#39;D&#39;,&#39;E&#39;,&#39;F&#39;,&#39;G&#39;,&#39;H&#39;,&#39;I&#39;,&#39;J&#39;,&#39;K&#39;,&#39;L&#39;,&#39;M&#39;,&#39;N&#39;,&#39;O&#39;,&#39;P&#39;,&#39;Q&#39;,&#39;X&#39;,&#39;Y&#39;,&#39;Z&#39;,&#39;W&#39;,&#39;S&#39;,&#39;R&#39;,&#39;T&#39;);<br/>$CHAR_ARR_LEN = count($CHAR_ARR) - 1;<br/>$code = &#39;&#39;;<br/>while(--$len > 0){ $code .= $CHAR_ARR[rand(0,$CHAR_ARR_LEN)]; }<br/>return $code;<br/>}<br/>$pdo = new PDO(&#39;mysql:host=localhost;dbname=ci_test&#39;,&#39;root&#39;,&#39;root&#39;);<br/>//查询当前时间已发放验证码数量<br/>$code_num_rs = $pdo->query("SELECT COUNT(*) as sum FROM code_test");<br/>$code_num_arr = $code_num_rs->fetch(PDO::FETCH_ASSOC);<br/>$code_num = $code_num_arr[&#39;sum&#39;];<br/>if($code_num < 1){<br>   sleep(2); //暂停2秒<br/>$code = get_code(6);<br/>var_dump( $pdo->query("INSERT INTO code_test (code,create_time) VALUES (&#39;$code&#39;,".time().")") );<br/>}<br/></p>
Salin selepas log masuk

  上述代码默认满足当前是开放时间,和码是不重复的; 

  在不考虑并发情况下流程:

  1)选查询当前数据库发放的验证码数量;

  2)如果还有名额,则生成验证码,插入到数据库,返回验证码到客户端;

  3)如果已满;则返回提示,已无名额;

2、并发情况下实现:

  那么看下上面代码在并发情况下得到的结果:

  测试并发,可以使用apache benchmark来测试,apache benchmark是APACHE旗下的HTTP SERVER的性能评测工具,通过cmd进入到apche的bin目录下,通过ab命令调用,如:ab -c 并发数量 -n 总访问量 url

<p style="margin-top: 5px; margin-bottom: 5px;">cb -c 100 -n 100 http://localhost/php_mulit.php<br/></p>
Salin selepas log masuk
Salin selepas log masuk

  这样就是100个用户同事去抢1个名额,在查询的时候,每个用户都查询到还有一个名额,则会去生成验证码,插入数据库,返回验证码;这样就造成了验证码发多了。事实上,运行完该命令,数据库多了13条记录,而不是一条。

  怎么避免这情况发生呢? 

  可以通过加排他锁来锁定判断到插入这个过程,保证这个判断流程任意一时间只有一个进程在运行。实现如下:

<p style="margin-top: 5px; margin-bottom: 5px;">//生成码<br/>function get_code($len){<br/>$CHAR_ARR = array(&#39;1&#39;,&#39;2&#39;,&#39;3&#39;,&#39;4&#39;,&#39;5&#39;,&#39;6&#39;,&#39;7&#39;,&#39;8&#39;,&#39;9&#39;,&#39;A&#39;,&#39;B&#39;,&#39;C&#39;,&#39;D&#39;,&#39;E&#39;,&#39;F&#39;,&#39;G&#39;,&#39;H&#39;,&#39;I&#39;,&#39;J&#39;,&#39;K&#39;,&#39;L&#39;,&#39;M&#39;,&#39;N&#39;,&#39;O&#39;,&#39;P&#39;,&#39;Q&#39;,&#39;X&#39;,&#39;Y&#39;,&#39;Z&#39;,&#39;W&#39;,&#39;S&#39;,&#39;R&#39;,&#39;T&#39;);<br/>$CHAR_ARR_LEN = count($CHAR_ARR) - 1;<br/>$code = &#39;&#39;;<br/>while(--$len > 0){ $code .= $CHAR_ARR[rand(0,$CHAR_ARR_LEN)]; }<br/>return $code;<br/>}<br/>$pdo = new PDO(&#39;mysql:host=localhost;dbname=ci_test&#39;,&#39;root&#39;,&#39;root&#39;);<br/>$fp = fopen(&#39;lock.txt&#39;,&#39;r&#39;);<br/>//通过排他锁 锁定该过程<br/>if(flock($fp,LOCK_EX)){<br/>//查询当前时间已发放验证码数量<br/>$code_num_rs = $pdo->query("SELECT COUNT(*) as sum FROM code_test");<br/>$code_num_arr = $code_num_rs->fetch(PDO::FETCH_ASSOC);<br/>$code_num = $code_num_arr[&#39;sum&#39;];<br/>if($code_num < 1){<br/>sleep(2);<br/>$code = get_code(6);<br/>var_dump( $pdo->query("INSERT INTO code_test (code,create_time) VALUES (&#39;$code&#39;,".time().")") );<br/>}<br/>flock($fp,LOCK_UN);<br/>fclose($fp);<br/>}<br/></p>
Salin selepas log masuk

通过flock函数来锁定该过程。

再次运行

<p style="margin-top: 5px; margin-bottom: 5px;">cb -c 100 -n 100 http://localhost/php_mulit.php<br/></p>
Salin selepas log masuk
Salin selepas log masuk

数据库只增加了一条记录,保证了并发情况下数据的正确。

相关推荐:

浏览器退出之后php还会继续执行吗的深入探究

php实现在线通讯录的实例

PHP如何高效读取大文件的实例对比

Atas ialah kandungan terperinci PHP通过加锁实现并发抢购功能. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan