<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<head><meta forua="true" http-equiv="Cache-Control" content="max-age=0" /></head>
<card title="解决php抢购秒杀抽奖等大流量并发入库导致的库存负数的问题(非/阻塞模式)" id="card1">
<p> 游客</p><p>
标题:解决php抢购秒杀抽奖等大流量并发入库导致的库存负数的问题(非/阻塞模式)<br/>
正文:<br/>
我们知道数据库处理sql是一条条处理的，假设购买商品的流程是这样的：sql1:查询商品库存if(库存数量 &amp;gt; 0)<br/>{<br/>  //生成订单...<br/>  sql2:库存-1<br/>}当没有并发时，上面的流程看起来是如此完美，假设同时两个人下单，而库存只有1个了，在sql1阶段两个人查询到的库存都是&amp;gt;0的，于是最终都执行了sql2，库存最后变为-1，超售了，要么补库存，要么等用户投诉吧。解决这个问题比较流行的思路：1.用额外的单进程处理一个队列，下单请求放到队列里，一个个处理，就不会有并发的问题了，但是要额外的后台进程以及延迟问题，不予考虑。2.数据库乐观锁，大致的意思是先查询库存，然后立马将库存+1，然后订单生成后，在更新库存前再查询一次库存，看看跟预期的库存数量是否保持一致，不一致就回滚，提示用户库存不足。3.根据update结果来判断，我们可以在sql2的时候加一个判断条件update ... where 库存&amp;gt;0，如果返回false，则说明库存不足，并回滚事务。4.借助文件排他锁，在处理下单请求的时候，用flock锁定一个文件，如果锁定失败说明有其他订单正在处理，此时要么等待要么直接提示用户&quot;服务器繁忙&quot;本文要说的是第4种方案，大致代码如下：阻塞(等待)模式&amp;lt;?php<br/>$fp = fopen(&quot;lock.txt&quot;, &quot;w+&quot;);<br/>if(flock($fp,LOCK_EX))<br/>{<br/>  //..处理订单<br/>  flock($fp,LOCK_UN);<br/>}<br/>fclose($fp);<br/>?&amp;gt;非阻塞模式&amp;lt;?php<br/>$fp = fopen(&quot;lock.txt&quot;, &quot;w+&quot;);<br/>if(flock($fp,LOCK_EX | LOCK_NB))<br/>{<br/>  //..处理订单<br/>  flock($fp,LOCK_UN);<br/>}<br/>else<br/>{<br/>  echo &quot;系统繁忙，请稍后再试&quot;;<br/>}<br/>fclose($fp);<br/>?&amp;gt;<br/><a href="http://camnpr.com/wap.asp?mode=WAP&amp;act=View&amp;id=1470&amp;Page=1">[&lt;&lt;]</a><a href="http://camnpr.com/wap.asp?mode=WAP&amp;act=View&amp;id=1470&amp;Page=1">[[1]]</a><a href="http://camnpr.com/wap.asp?mode=WAP&amp;act=View&amp;id=1470&amp;Page=1">[&gt;&gt;]</a><br/>
<br/>
<a href="wap.asp?act=Com&amp;id=1470">查看评论(0)</a><br/>
<a href="wap.asp?act=AddCom&amp;inpId=1470">发表评论</a><br/><br/>

<br/>

<br/>
<a href="http://camnpr.com/wap.asp">首页</a>
</p>
</card>
</wml>