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中对数据库操作的封装
Oct 09 PHP
分享PHP入门的学习方法
Jan 02 PHP
PHP下通过系统信号量加锁方式获取递增序列ID
Sep 25 PHP
PHP怎么实现网站保存快捷方式方便用户随时浏览
Aug 15 PHP
php使用百度天气接口示例
Apr 22 PHP
PHP中date与gmdate的区别及默认时区设置
May 12 PHP
Laravel框架路由配置总结、设置技巧大全
Sep 03 PHP
PHP中auto_prepend_file与auto_append_file用法实例分析
Sep 22 PHP
PHP统计目录大小的自定义函数分享
Nov 18 PHP
php调用KyotoTycoon简单实例
Apr 02 PHP
php实现获取农历(阴历)、节日、节气的类与用法示例
Nov 20 PHP
PHP实现字符串的全排列详解
Apr 24 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
Zend公司全球首推PHP认证
2006/10/09 PHP
提升PHP速度全攻略
2006/10/09 PHP
探讨php中header的用法详解
2013/06/07 PHP
js Event对象的5种坐标
2011/09/12 Javascript
jQuery当鼠标悬停时放大图片的效果实例
2013/07/03 Javascript
javascript 回调函数详解
2014/11/11 Javascript
Javascript中判断对象是否为空
2015/06/10 Javascript
Bootstrap开关(switch)控件学习笔记分享
2016/05/30 Javascript
jQuery实现日期联动效果实例
2016/07/26 Javascript
JS获取当前使用的浏览器名字以及版本号实现方法
2016/08/19 Javascript
扩展jquery easyui tree的搜索树节点方法(推荐)
2016/10/28 Javascript
Bootstrap的popover(弹出框)2秒后定时消失的实现代码
2017/02/27 Javascript
JS正则表达式验证账号、手机号、电话和邮箱是否合法
2017/03/08 Javascript
使用vue框架 Ajax获取数据列表并用BootStrap显示出来
2017/04/24 Javascript
微信小程序 wx.request方法的异步封装实例详解
2017/05/18 Javascript
浅谈angular4.0中路由传递参数、获取参数最nice的写法
2018/03/12 Javascript
es6中reduce的基本使用方法
2019/09/10 Javascript
浅析vue cli3 封装Svgicon组件正确姿势(推荐)
2020/04/27 Javascript
Openlayers显示地理位置坐标的方法
2020/09/28 Javascript
手写Vue2.0 数据劫持的示例
2021/03/04 Vue.js
Python中的高级数据结构详解
2015/03/27 Python
一键搞定python连接mysql驱动有关问题(windows版本)
2016/04/23 Python
Python简单检测文本类型的2种方法【基于文件头及cchardet库】
2016/09/18 Python
Python 使用requests模块发送GET和POST请求的实现代码
2016/09/21 Python
Flask实现图片的上传、下载及展示示例代码
2018/08/03 Python
Python修改文件往指定行插入内容的实例
2019/01/30 Python
分析经典Python开发工程师面试题
2019/04/08 Python
Python银行系统实战源码
2019/10/25 Python
django表单中的按钮获取数据的实例分析
2020/07/31 Python
python实现画图工具
2020/08/27 Python
想学画画?python满足你!
2020/12/24 Python
Css3新特性应用之视觉效果实例
2016/12/12 HTML / CSS
供用电专业求职信
2014/07/07 职场文书
《卖火柴的小女孩》教学反思
2016/02/19 职场文书
2016年春季趣味运动会开幕词
2016/03/04 职场文书
Python实现将多张图片合成MP4视频并加入背景音乐
2022/04/28 Python