对于商品抢购等并发场景下,可能会出现超卖的现象,这时就需要解决并发所带来的这些问题了
PHP语言中并没有原生的提供并发的解决方案,因此就需要借助其他方式来实现并发控制。
方案一:使用文件锁排它锁
flock函数用于获取文件的锁,这个锁同时只能被一个线程获取到,其它没有获取到锁的线程要么阻塞,要么获取失败
在获取到锁的时候,先查询库存,如果库存大于0,则进行下订单操作,减库存,然后释放锁
 
方案二:使用MySQL数据库提供的悲观锁
Innodb存储引擎支持行级锁,当某行数据被锁定时,其他进程不能对这行数据进行操作
先查询并锁定行:select stock_num from table where id=1 for update
if (stock_num > 0) {
    //下订单
    update table set stock_num = stock - 1 where id = 1
}
 
方案三:使用队列
将用户的下单请求依次存入一个队列中,后台用一个单独的进程处理队列中的下单请求
 
方案四:使用Redis
redis的操作都是原子性的,可以将商品的库存存入redis中,下单之前对库存进行decr操作,如果返回的值大于等于0等可以下单,否则不能下单,这种方式效率较高
if (redis - > get('stock_num') > 0) {
    stock_num = redis - > decr('stock_num')
    if (stock_num >= 0) {
        //下订单
    } else {
        //库存不足
    }
} else {
    //库存不足
}
 
其他并发问题:
在现实应用中,很多情况下会把数据存入缓存,当缓存失效时,去数据库取数据并重新设置缓存,如果这时并发量很大,会有很多进程同时去数据库取数据,导致很多请求
穿透到数据库,而使数据库奔溃,这里可用文件锁来解决
$data = $cache - > get('key');
if (!$data) {
    $fp = fopen('lockfile');
    if (flock($fp, LOCK_EX)) {
        $data = $cache - > get('key'); //拿到锁后再次检查缓存,这时可能已经有了 
        if (!$data) {
            $data = mysql - > query();
            $cache - > set('key', $data);
        }
        flock($fp, LOCK_UN);
    }
    fclose($fp);
}

php 处理并发问题的更多相关文章

  1. .Net多线程编程—并发集合

    并发集合 1 为什么使用并发集合? 原因主要有以下几点: System.Collections和System.Collections.Generic名称空间中所提供的经典列表.集合和数组都不是线程安全 ...

  2. [ 高并发]Java高并发编程系列第二篇--线程同步

    高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...

  3. [高并发]Java高并发编程系列开山篇--线程实现

    Java是最早开始有并发的语言之一,再过去传统多任务的模式下,人们发现很难解决一些更为复杂的问题,这个时候我们就有了并发. 引用 多线程比多任务更加有挑战.多线程是在同一个程序内部并行执行,因此会对相 ...

  4. 关于如何提高Web服务端并发效率的异步编程技术

    最近我研究技术的一个重点是java的多线程开发,在我早期学习java的时候,很多书上把java的多线程开发标榜为简单易用,这个简单易用是以C语言作为参照的,不过我也没有使用过C语言开发过多线程,我只知 ...

  5. 如何在高并发环境下设计出无锁的数据库操作(Java版本)

    一个在线2k的游戏,每秒钟并发都吓死人.传统的hibernate直接插库基本上是不可行的.我就一步步推导出一个无锁的数据库操作. 1. 并发中如何无锁. 一个很简单的思路,把并发转化成为单线程.Jav ...

  6. Java多线程基础——对象及变量并发访问

    在开发多线程程序时,如果每个多线程处理的事情都不一样,每个线程都互不相关,这样开发的过程就非常轻松.但是很多时候,多线程程序是需要同时访问同一个对象,或者变量的.这样,一个对象同时被多个线程访问,会出 ...

  7. 多线程的通信和同步(Java并发编程的艺术--笔记)

    1. 线程间的通信机制 线程之间通信机制有两种: 共享内存.消息传递.   2. Java并发 Java的并发采用的是共享内存模型,Java线程之间的通信总是隐式执行,通信的过程对于程序员来说是完全透 ...

  8. 伪共享(false sharing),并发编程无声的性能杀手

    在并发编程过程中,我们大部分的焦点都放在如何控制共享变量的访问控制上(代码层面),但是很少人会关注系统硬件及 JVM 底层相关的影响因素.前段时间学习了一个牛X的高性能异步处理框架 Disruptor ...

  9. 编写高质量代码:改善Java程序的151个建议(第8章:多线程和并发___建议126~128)

    建议126:适时选择不同的线程池来实现 Java的线程池实现从根本上来说只有两个:ThreadPoolExecutor类和ScheduledThreadPoolExecutor类,这两个类还是父子关系 ...

  10. 理解Storm并发

    作者:Jack47 PS:如果喜欢我写的文章,欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源. 注:本文主要内容翻译自understanding-the-parall ...

随机推荐

  1. TypeScript装饰器(decorators)

    装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上,可以修改类的行为. 装饰器使用 @expression这种形式,expression求值后必须为一个函数,它会在运行时被 ...

  2. URL编码的方法

    Global 对象的encodeURI()和encodeURIComponent()方法可以对URI(Uniform ResourceIdentifiers,通用资源标识符)进行编码,以便发送给浏览器 ...

  3. UE4 小笔记

    1,设置postprocess材质时使用Add or Update Blendable 用Make PostprocessSetting会报警告,因为C++代码中没有设置为BlueprintReadW ...

  4. lnmp一键安装的卸载

    http://blog.csdn.net/lansetiankong12/article/details/48130507  如果是lnmp一键安装的 进入安装包目录 [root@www home]# ...

  5. php错误 分析

    ---------------------------------------------------------------------------------------------------- ...

  6. android 基础03 -- Intent

    Android 中的 Intent 是将要执行的操作的一种抽象的描述,是一个用于Android 各个组件之间传递消息的对象. Intent 的基本用法 Intent 基本的使用方法主要有三种: 启动一 ...

  7. bug 对应

    异常1:not-null property references a null or transient value解决方法:将“一对多”关系中的“一”方,not-null设置为false http: ...

  8. mysql explain用法和结果的含义

    转自:http://blog.chinaunix.net/uid-540802-id-3419311.html explain显示了mysql如何使用索引来处理select语句以及连接表.可以帮助选择 ...

  9. 小打卡PRD

    目标:打造一款不同于市场上的公开打卡app的产品 理念:通过监督和鼓励,和相同圈子的人一起互相鼓励.分享及监督,共同进步. 优点: 模板消息通知,网上基本通过小程序中逻辑层JS完成推送的请求,小打卡在 ...

  10. 通过Azure 存储账号URL鉴别是标准磁盘还是高性能磁盘

    对于不知道虚拟机磁盘是标准磁盘还是高性能磁盘时,我们可以通过nslookup解析存储账号的URL,来判断存储账号的类型,从而得知虚拟磁盘的类型 1.标准存储账号的解析结果,字母"st&quo ...