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 相关文章推荐
1.PHP简介
Oct 09 PHP
一步一步学习PHP(4) php 函数 补充2
Feb 15 PHP
php radio 单选框获取与保持值的实现代码
May 15 PHP
PHP 年龄计算函数(精确到天)
Jun 07 PHP
php保存二进制原始数据为图片的程序代码
Oct 14 PHP
php实现可逆加密的方法
Aug 11 PHP
使用PHP生成图片的缩略图的方法
Aug 18 PHP
基于PHP如何把汉字转化为拼音
Dec 11 PHP
PHP7+Nginx的配置与安装教程详解
May 10 PHP
PHP基于GD库的图像处理方法小结
Sep 27 PHP
PHP实现二维数组去重功能示例
Jan 12 PHP
Laravel框架使用技巧之使用url()全局函数返回前一个页面的地址方法详解
Apr 06 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
Yii框架引入coreseek分页功能示例
2019/02/08 PHP
JavaScript与函数式编程解释
2007/04/27 Javascript
基于jquery的表头固定的若干方法
2011/01/27 Javascript
使用jquery实现div的tab切换实例代码
2013/05/27 Javascript
24款热门实用的jQuery插件推荐
2014/12/24 Javascript
JavaScript实现自动消除按钮功能的方法
2015/08/05 Javascript
轻松实现Bootstrap图片轮播
2020/04/20 Javascript
浅析Javascript中bind()方法的使用与实现
2016/04/29 Javascript
浅谈javascript中执行环境(作用域)与作用域链
2016/12/08 Javascript
javascript history对象详解
2017/02/09 Javascript
AngularJS实现路由实例
2017/02/12 Javascript
JS实现页面打印功能
2017/03/16 Javascript
微信小程序中的swiper组件详解
2017/04/14 Javascript
JS按条件 serialize() 对应标签的使用方法
2017/07/24 Javascript
JS滚轮控制图片缩放大小和拖动的实例代码
2018/11/20 Javascript
JS实现获取当前所在周的周六、周日示例分析
2019/05/11 Javascript
微信小程序云开发如何使用云函数生成二维码
2019/05/18 Javascript
Webpack中loader打包各种文件的方法实例
2019/09/03 Javascript
微信小程序实现分页加载效果
2020/11/19 Javascript
[02:05]2014DOTA2西雅图邀请赛 老队长全明星大猜想谁不服就按进显示器
2014/07/08 DOTA
[54:15]DOTA2-DPC中国联赛 正赛 DLG vs Dragon BO3 第二场2月1日
2021/03/11 DOTA
python类继承用法实例分析
2014/10/10 Python
Python中装饰器的一个妙用
2015/02/08 Python
Python httplib模块使用实例
2015/04/11 Python
在Pycharm中修改文件默认打开方式的方法
2019/01/17 Python
python如何判断IP地址合法性
2020/04/05 Python
德国最大的网上足球商店:11teamsports
2019/09/11 全球购物
生产车间实习自我鉴定
2013/09/23 职场文书
《梅花魂》教学反思
2014/04/30 职场文书
设计大赛策划方案
2014/06/13 职场文书
2015年学校体育工作总结
2015/04/22 职场文书
呼啸山庄读书笔记
2015/06/29 职场文书
大学毕业典礼致辞
2015/07/29 职场文书
带你彻底理解JavaScript中的原型对象
2021/04/14 Javascript
go web 预防跨站脚本的实现方式
2021/06/11 Golang
vue 自定义组件添加原生事件
2022/04/21 Vue.js