php解决抢购秒杀抽奖等大流量并发入库导致的库存负数的问题


Posted in PHP onJune 19, 2014

我们知道数据库处理sql是一条条处理的,假设购买商品的流程是这样的:

sql1:查询商品库存

if(库存数量 > 0)
{
  //生成订单...
  sql2:库存-1
}

当没有并发时,上面的流程看起来是如此完美,假设同时两个人下单,而库存只有1个了,在sql1阶段两个人查询到的库存都是>0的,于是最终都执行了sql2,库存最后变为-1,超售了,要么补库存,要么等用户投诉吧。

解决这个问题比较流行的思路:

1.用额外的单进程处理一个队列,下单请求放到队列里,一个个处理,就不会有并发的问题了,但是要额外的后台进程以及延迟问题,不予考虑。

2.数据库乐观锁,大致的意思是先查询库存,然后立马将库存+1,然后订单生成后,在更新库存前再查询一次库存,看看跟预期的库存数量是否保持一致,不一致就回滚,提示用户库存不足。

3.根据update结果来判断,我们可以在sql2的时候加一个判断条件update ... where 库存>0,如果返回false,则说明库存不足,并回滚事务。

4.借助文件排他锁,在处理下单请求的时候,用flock锁定一个文件,如果锁定失败说明有其他订单正在处理,此时要么等待要么直接提示用户"服务器繁忙"

本文要说的是第4种方案,大致代码如下:

阻塞(等待)模式

<?php
$fp = fopen("lock.txt", "w+");
if(flock($fp,LOCK_EX))
{
  //..处理订单
  flock($fp,LOCK_UN);
}
fclose($fp);
?>

非阻塞模式

<?php
$fp = fopen("lock.txt", "w+");
if(flock($fp,LOCK_EX | LOCK_NB))
{
  //..处理订单
  flock($fp,LOCK_UN);
}
else
{
  echo "系统繁忙,请稍后再试";
}

fclose($fp);
?>
PHP 相关文章推荐
细谈php中SQL注入攻击与XSS攻击
Jun 10 PHP
PHP gbk环境下json_dencode传送来的汉字
Nov 13 PHP
浅析Dos下运行php.exe,出现没有找到php_mbstring.dll 错误的解决方法
Jun 29 PHP
php生成excel列名超过26列大于Z时的解决方法
Dec 29 PHP
THINKPHP2.0到3.0有哪些改进之处
Jan 04 PHP
PHP借助phpmailer发送邮件
May 11 PHP
[原创]ThinkPHP让../Public在模板不解析(直接输出)的方法
Oct 09 PHP
在Mac OS上搭建PHP的Yii框架及相关测试环境
Feb 14 PHP
Zend Framework入门之环境配置及第一个Hello World示例(附demo源码下载)
Mar 21 PHP
php简单备份与还原MySql的方法
May 09 PHP
phpStudy配置多站点多域名方法及遇到的403错误解决方法
Oct 19 PHP
Laravel统计一段时间间隔的数据方法
Oct 09 PHP
PHP base64编码后解码乱码的解决办法
Jun 19 #PHP
PHP安全的URL字符串base64编码和解码
Jun 19 #PHP
PHP中的多行字符串传递给JavaScript的两种方法
Jun 19 #PHP
ThinkPHP模板引擎之导入资源文件方法详解
Jun 18 #PHP
ThinkPHP CURD方法之field方法详解
Jun 18 #PHP
ThinkPHP CURD方法之data方法详解
Jun 18 #PHP
ThinkPHP CURD方法之order方法详解
Jun 18 #PHP
You might like
网友原创的PHP模板类代码
2008/09/07 PHP
PHP下利用header()函数设置浏览器缓存的代码
2010/09/01 PHP
PHP 的ArrayAccess接口 像数组一样来访问你的PHP对象
2010/10/12 PHP
php 地区分类排序算法
2013/07/01 PHP
php文件服务实现虚拟挂载其他目录示例
2014/04/17 PHP
在PHP中使用FastCGI解析漏洞及修复方案
2015/11/10 PHP
PHP面向对象之领域模型+数据映射器实例(分析)
2017/06/21 PHP
PHP使用redis消息队列发布微博的方法示例
2017/06/22 PHP
js弹出层之1:JQuery.Boxy (二)
2011/10/06 Javascript
利用javascript实现禁用网页上所有文本框,下拉菜单,多行文本域
2013/12/14 Javascript
JavaScript原型链示例分享
2014/01/26 Javascript
当前流行的JavaScript代码风格指南
2014/09/10 Javascript
JavaScript中的继承方式详解
2015/02/11 Javascript
Flow之一个新的Javascript静态类型检查器
2015/12/21 Javascript
JavaScript学习笔记之数组的增、删、改、查
2016/03/23 Javascript
引用jquery框架后出错的解决方法
2016/08/09 Javascript
微信小程序 网络API 上传、下载详解
2016/11/09 Javascript
JavaScript实现邮箱地址自动匹配功能代码
2016/11/28 Javascript
JS面向对象的程序设计相关知识小结
2018/05/26 Javascript
VueJS 取得 URL 参数值的方法
2019/07/19 Javascript
Python3读取zip文件信息的方法
2015/05/22 Python
Python实现获取磁盘剩余空间的2种方法
2017/06/07 Python
python ---lambda匿名函数介绍
2019/03/13 Python
Python-Tkinter Text输入内容在界面显示的实例
2019/07/12 Python
python实现简单俄罗斯方块
2020/03/13 Python
详解python爬取弹幕与数据分析
2020/11/14 Python
selenium框架中driver.close()和driver.quit()关闭浏览器
2020/12/08 Python
美国户外生活方式品牌:Eddie Bauer
2016/12/28 全球购物
德国BA保镖药房韩文网:kr.ba.de
2017/09/04 全球购物
String s = new String(“xyz”);创建了几个String Object?
2015/08/05 面试题
如何用Java判断一个文件或目录是否存在
2012/11/19 面试题
财务工作犯错检讨书
2014/10/07 职场文书
大学生自我推荐信范文
2015/03/24 职场文书
员工聘用合同范本
2015/09/21 职场文书
Python中X[:,0]和X[:,1]的用法
2021/05/10 Python
使用SQL实现车流量的计算的示例代码
2022/02/28 SQL Server