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

sql1:查询商品库存

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

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

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

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

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

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

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

//阻塞(等待)模式

1
2
3
4
5
6
7
8
9
<?php
$fp = fopen("lock.txt", "w+");
if(flock($fp,LOCK_EX))
{
    //..处理订单
    flock($fp,LOCK_UN);
}
 
fclose($fp);

//非阻塞模式

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
$fp = fopen("lock.txt", "w+");
if(flock($fp,LOCK_EX | LOCK_NB))
{
    //..处理订单
    flock($fp,LOCK_UN);
}
else
{
    echo "系统繁忙,请稍后再试";
}
 
fclose($fp);

php解决下单、抽奖并发导致的库存负数的问题的更多相关文章

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

    我们知道数据库处理sql是一条条处理的,假设购买商品的流程是这样的: sql1:查询商品库存 1 if(库存数量 > 0) 2 { 3 //生成订单 4 //库存-1 5 > 当没有并发时 ...

  2. 利用redis实现分布式事务锁,解决高并发环境下库存扣减

    利用redis实现分布式事务锁,解决高并发环境下库存扣减   问题描述: 某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 解决方案一 利用数据 ...

  3. redis分布式锁扣减库存弊端: 吞吐量低, 解决方法:使用 分段锁 分布式分段锁并发扣减库存--代码实现

    package tech.codestory.zookeeper.aalvcai.ConcurrentHashMapLock; import lombok.AllArgsConstructor; im ...

  4. EntityFramework Core并发导致显示插入主键问题

    前言 之前讨论过EntityFramework Core中并发问题,按照官网所给并发冲突解决方案以为没有什么问题,但是在做单元测试时发现too young,too siimple,下面我们一起来看看. ...

  5. EntityFramework Core并发导致显式插入主键问题

    前言 之前讨论过EntityFramework Core中并发问题,按照官网所给并发冲突解决方案以为没有什么问题,但是在做单元测试时发现too young,too simple,下面我们一起来看看. ...

  6. 解决删除/升级Python导致Ubuuntu无法进入桌面的问题

    找到问题的原因后于是换个思路,想大概修复了python,Ubuntu进入桌面应该也就没啥问题了.于是重新安装Python发现还是无济于事.也通过/usr/bin/python: can't find ...

  7. (C#)使用队列(Queue)解决简单的并发问题

    (C#)使用队列(Queue)解决简单的并发问题 2015-07-16 13:04 13265人阅读 评论(8) 收藏 举报  分类: Asp.Net(8)  版权声明:本文为博主原创文章,未经博主允 ...

  8. 讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(中)- IOS不为人知的Bug

    前言: 话说昨晚还是前晚,写了一篇:讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(上) 文章写到最后时,多了很多莫名奇妙的问题!!! 为了解决了这些莫名奇妙的问题,我又战斗了2 ...

  9. 讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(下)- block中任性用self

    前言: 在处理完框架内存泄漏的问题后,见上篇:讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(中)- IOS不为人知的Bug 发现业务代码有一个地方的内存没释放,原因很也简单: ...

随机推荐

  1. Bzoj 1984: 月下“毛景树” 树链剖分

    1984: 月下“毛景树” Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 1282  Solved: 410[Submit][Status][Discu ...

  2. Caffe 在 Ubuntu 中安装

    Ubuntu Installation General dependencies sudo apt-get install libprotobuf-dev libleveldb-dev libsnap ...

  3. hdoj 2036 改革春风吹满地

    改革春风吹满地 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  4. hdoj 4006 The kth great number【优先队列】

    The kth great number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Oth ...

  5. 关于PHP程序员解决问题的能力

    这个话题老生长谈了,在面试中必然考核的能力中,我个人认为解决问题能力是排第一位的,比学习能力优先级更高.解决问题的能力既能看出程序员的思维能力,应变能力,探索能力等,又可以看出他的经验.如果解决问题能 ...

  6. tcpdump来抓取执行的sql语句

    # tcpdump -n -nn -tttt -i eth1 -s 65535 'port 3306' -w tcpdump_mysql.ret -C 100 一个TCP包中包含多个mysql协议包, ...

  7. LabVIEW系列——错误簇的传递

    从以下示例可以得出结论: 1.图一出现的三种错误,分别位于打开/创建/替换文件函数,写入文本文件函数,读取文件文件函数.说明三个函数都被运行了. 2.图二只出现了一种错误,位于打开/创建/替换文件函数 ...

  8. QTreeWidget实现动态加载本地文件系统

    QT之前没有接触过,之所以做这个也是被临时拉去GoldenFarm组去做渲染的客户端:还别说,虽说是第一次,做出来的这个东西倒是挺让我满意的.先说一下具体需求,然后再上图吧: 渲染时在选择场景文件时, ...

  9. 剖析@weakify 和 @strongify

    前言 使用RAC的时候我们常会看到这两个宏@weakify(self).@strongify(self),用来防止使用block时出现引用闭环. 今天看YYKit的时候,看到里面也写了类似的宏,还是来 ...

  10. 基于bootstrap面板的类别多选栏

    1.html部分 <div class="panel panel-default"> <div class="panel-heading"&g ...