抢购场景完全靠数据库来扛,压力是非常大的,我们在最近的一次抢购活动改版中,采用了redis队列+mysql事务控制的方案,画了个简单的流程图:

先来就库存超卖的问题作描述:一般电子商务网站都会遇到如团购、秒杀、特价之类的活动,而这样的活动有一个共同的特点就是访问量激增、上千甚至上万人抢购一个商品。然而,作为活动商品,库存肯定是很有限的,如何控制库存不让出现超买,以防止造成不必要的损失是众多电子商务网站程序员头疼的问题,这同时也是最基本的问题。

从技术方面剖析,很多人肯定会想到事务,但是事务是控制库存超卖的必要条件,但不是充分必要条件。

举例:

总库存:4个商品

请求人:a、1个商品 b、2个商品 c、3个商品

程序如下:

beginTranse(开启事务)
try{
$result = $dbca->query('select amount from s_store where postID = 12345');
if(result->amount > 0){
//quantity为请求减掉的库存数量
$dbca->query('update s_store set amount = amount - quantity where postID = 12345');
}
}catch($e Exception){
rollBack(回滚)
}
commit(提交事务)

以上代码就是我们平时控制库存写的代码了,大多数人都会这么写,看似问题不大,其实隐藏着巨大的漏洞。数据库的访问其实就是对磁盘文件的访问,数据库中的表其实就是保存在磁盘上的一个个文件,甚至一个文件包含了多张表。例如由于高并发,当前有三个用户a、b、c三个用户进入到了这个事务中,这个时候会产生一个共享锁,所以在select的时候,这三个用户查到的库存数量都是4个,同时还要注意,mysql innodb查到的结果是有版本控制的,在其他用户更新没有commit之前(也就是没有产生新版本之前),当前用户查到的结果依然是就版本;

然后是update,假如这三个用户同时到达update这里,这个时候update更新语句会把并发串行化,也就是给同时到达这里的是三个用户排个序,一个一个执行,并生成排他锁,在当前这个update语句commit之前,其他用户等待执行,commit后,生成新的版本;这样执行完后,库存肯定为负数了。但是根据以上描述,我们修改一下代码就不会出现超买现象了,代码如下:

beginTranse(开启事务)
try{
//quantity为请求减掉的库存数量
$dbca->query('update s_store set amount = amount - quantity where postID = 12345');
$result = $dbca->query('select amount from s_store where postID = 12345');
if(result->amount < 0){
throw new Exception('库存不足');
}
}catch($e Exception){
rollBack(回滚)
}
commit(提交事务)

MYSQL处理高并发,防止库存超卖(图解)的更多相关文章

  1. mysql悲观锁处理赠品库存超卖的情况

    处理库存超卖的情况前,先了解下什么是乐观锁和悲观锁,下面的几篇博客已经介绍的比较详细了,我就不在赘述其原理了 [MySQL]悲观锁&乐观锁 对mysql乐观锁.悲观锁.共享锁.排它锁.行锁.表 ...

  2. 记一次项目中解决 -- 并发减库存超卖问题过程(Java)

    起因:项目中要做预约功能,首先每天的余票都是有上限的,自然不能出现超卖的情况 基于我们项目是单体分布式的springcloud部署,我想了下 第一种方法,直接mysql加行锁,要update这条库存数 ...

  3. mysql处理高并发,防止库存超卖

    先来就库存超卖的问题作描述:一般电子商务网站都会遇到如团购.秒杀.特价之类的活动,而这样的活动有一个共同的特点就是访问量激增.上千甚至上万人抢购一个商品.然而,作为活动商品,库存肯定是很有限的,如何控 ...

  4. Mysql在高并发情况下,防止库存超卖而小于0的解决方案

    背景: 本人上次做申领campaign的PHP后台时,因为项目上线后某些时段同时申领的人过多,导致一些专柜的存货为负数(<0),还好并发量不是特别大,只存在于小部分专柜而且一般都是-1的状况,没 ...

  5. <转> mysql处理高并发,防止库存超卖

    先来就库存超卖的问题作描述:一般电子商务网站都会遇到如团购.秒杀.特价之类的活动,而这样的活动有一个共同的特点就是访问量激增.上千甚至上万人抢购 一个商品.然而,作为活动商品,库存肯定是很有限的,如何 ...

  6. MySQL防止库存超卖方法总结

    订单超卖问题是涉及到库存项目的重中之重,这里我总结一下常用的方法 1.简单处理[update & select 合并](乐观锁) beginTranse(开启事务)$num = 1; try{ ...

  7. PHP+Redis实现高并发下商品超卖问题

    对于一些有一定用户量的电商网站,如果只是单纯的使用关系型数据库(如MySQL.Oracle)来做抢购,对数据库的压力是非常大的,而且如果不使用好数据库的锁机制,还会导致商品.优惠券超卖的问题.我所在的 ...

  8. PHP+Redis链表解决高并发下商品超卖问题

    目录 实现原理 实现步骤 上一篇文章聊了一下使用Redis事务来解决高并发商品超卖问题,今天我们来聊一下使用Redis链表来解决高并发商品超卖问题. 实现原理 使用redis链表来做,因为pop操作是 ...

  9. 使用Redis分布式锁处理并发,解决超卖问题

    一.使用Apache ab模拟并发压测 1.压测工具介绍 $ ab -n 100 -c 100 http://www.baidu.com/ -n表示发出100个请求,-c模拟100个并发,相当是100 ...

随机推荐

  1. Davinci-DM6467板子-外围器件的I2C地址的疑惑解答

    这篇文即调试标清视频或者说调试TVP5147和ADV7343所使用的程序名称为video_sd_playback_480i_composite 我们用的是合众达公司(SEED)的SEED-DVSD64 ...

  2. springmvc框架自带的异常处理器SimpleMappingExceptionResolver的使用

    使用分三步 1.定义异常类 2.在处理器中的用法 3.在springmvc配置文件中需要加配置

  3. MyBatis 延迟加载 加载时机

  4. linux 正则表达式

    redis-cli INFO|tr -d '\r'|egrep -v '^(#.*)?$'|sed -E 's/^([^:]*):(.*)$/redisInfo[\1]="\2"/ ...

  5. LevelDB Compaction操作

    [LevelDB Compaction操作] 对于LevelDb来说,写入记录操作很简单,删除记录仅仅写入一个删除标记就算完事,但是读取记录比较复杂,需要在内存以及各个层级文件中依照新鲜程度依次查找, ...

  6. JQuery:选择器、动画、AJAX请求

    选择器 1.事件编程与动画效果 一个选择器可以在概念上理解为指针.借助与JQuery库中的选择器$,线程可以获取到界面元素的引用,从而可以调用 ready().click()方法把用户事件和动作方法关 ...

  7. linux 安装php7 Nginx

    这里 记录下 本屌安装linux  下安装php7 即遇到的问题. wget http://cn2.php.NET/distributions/php-7.0.4.tar.gz tar zxvf ph ...

  8. iOS正确解决隐藏导航栏后push和pop或dismiss和present闪黑问题

    情景: 一级页面不显示导航栏 ,二级页面显示导航栏. 方法一 适用于push/pop: 一级页面中 - (void)viewWillAppear:(BOOL)animated { [super vie ...

  9. 使用matplotlib画双纵轴坐标

    一.前言 本文主要使用matplotlib,实现双纵轴坐标的图表绘制.笔者python版本为2.7.15. 二.实践及效果 1. 需求 某个有这么一个成绩表,分别是名字,本次成绩以及进步幅度,现在需要 ...

  10. Linux --centos7 开机启动设置

    以Linux下指定sun用户在linux开机时执行/home/sun/startrun.sh为例: 以root登录linux 执行vi /etc/rc.d/rc.local 在文档末尾添加一行语句:s ...