对于商品抢购等并发场景下,可能会出现超卖的现象,这时就需要解决并发所带来的这些问题了
在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. linux日志查看命令

    tail tail 命令用于显示文本文件的末尾几行, 对于监控文件日志特别有用 tail example.txt #显示文件 example.txt 的后十行内容: tail -n 20 exampl ...

  2. React源码解析:setState

    先来几个例子热热身: ......... constructor(props){ super(props); this.state = { index: 0 } } componentDidMount ...

  3. apache日志管理【转】

    web服务器日志轮循比较好的方式有三种:第一种方法是利用Linux系统自身的日志文件轮循机制:logrotate:第二种方法是利用apache自带的日志轮循程序rotatelogs:第三种是使用在ap ...

  4. [Git] git log命令

    这是git的新系列,不常用的命令和其参数比较容易记不住,干脆将常用的记录下来,日后查查方便也是好的,一篇文章一个git命令,长短根据命令有所不同. git log命令主要用于查看提交历史,同时根据添加 ...

  5. 更改Patrol Agent的密码

    大家可以使用P3console去做,具体方法请见:http://wenku.baidu.com/link?url=HbSzxNV2SPrlpk_Bfmcg0CNZuAlyX4jgdp4vbrxmynv ...

  6. 使用jQuery的ajax调用action的例子

    直接使用ajax请求会比较繁琐,但是jQuery为我们提供了简单使用ajax的方法. 下面是一个在jQuery easyUI中,利用ajax请求,使下拉菜单关联文本框的例子.其中ajax请求就是8-1 ...

  7. css 块状元素与行内元素(内联元素)的理解

    块状元素: 它一般是其他元素的容器元素,可以容纳块状元素和行内元素,它默认是不会和其他元素同一行的,即相当于两个块状元素写一起是垂直布局的.最常用的是div和p 行内元素: 行内元素又称内联元素,它只 ...

  8. android新建项目

    MinMum Required SDK :最低支持的Android api的版本,你的应用不能在低于这个版本的手机上面运行 Target SDK:你的应用最高支持android api版本 Compi ...

  9. CentOS 通过yum来升级php到php5.6

    在文章中,我们将展示在centOS系统下如果将php升级到5.6,之前通过yum来安装lamp环境,直接升级的话,提示没有更新包,也就是说默认情况下php5.3.3是最新 1.查看已经安装的php版本 ...

  10. 【转】awk内置变量

    awk是个优秀文本处理工具,可以说是一门程序设计语言.下面是awk内置变量. 一.内置变量表 属性 说明 $0 当前记录(作为单个变量) $1~$n 当前记录的第n个字段,字段间由FS分隔 FS 输入 ...