建表

1.订单表

CREATE TABLE `order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_sn` varchar(45) NOT NULL DEFAULT '0' COMMENT '订单编号',
`goods_id` int(11) NOT NULL DEFAULT '0' COMMENT '商品id',
`uid` int(11) NOT NULL DEFAULT '0' COMMENT '用户id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='订单表';

2.库存表

CREATE TABLE `stock` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`goods_id` int(11) NOT NULL DEFAULT '0' COMMENT '商品id',
`num` int(11) NOT NULL DEFAULT '0' COMMENT '剩余库存',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='库存';

在库存表插入一条数据id=1, goods_id=1,num=10

测试超卖

使用PHP的laravel框架测试

1.PHP代码

    public function index()
{
//模拟接受到的数据
$params = [
'goods_id' => 1,//商品id
'uid' => mt_rand(1, 1000),//随机用户uid
'num' => 1,//购买的数量
];
//查库存
$stockInfo = DB::table('stock')->where('goods_id', $params['goods_id'])->first('num');
$remain = $stockInfo->num - $params['num'];
if ($remain >= 0) {
$data = [
'order_sn' => date('YmdHis') . mt_rand(1000, 9999),
'goods_id' => $params['goods_id'],
'uid' => $params['uid'],
];
//插入订单
DB::table('order')->insert($data);
//更新库存--num字段是无符号类型
DB::table('stock')->where('goods_id', $params['goods_id'])->decrement('num', $params['num']);
return '抢到了';
} else {
return '暂无库存';
}
}

2.使用ab压测(ab压测详细使用https://www.cnblogs.com/wangzhaobo/p/8296298.html)

ab -c 100 -n 100 "http://l8.com/"

如果没有出现超卖,就再测试一下,一般3次之内就会出现超卖

防止超卖方法

1.使用mysql排它锁

//使用mysql排它锁防止超卖
public function index2()
{
//模拟接受到的数据
$params = [
'goods_id' => 1,//商品id
'uid' => mt_rand(1,1000),//随机用户uid
'num' => 1,//购买的数量
];
//开始事物
DB::beginTransaction();
//查库存
$stockInfo = DB::table('stock')->where('goods_id',$params['goods_id'])->lockForUpdate()->first('num');
$remain = $stockInfo->num-$params['num'];
if($remain>=0){
$data = [
'order_sn' => date('YmdHis').mt_rand(1000,9999),
'goods_id' => $params['goods_id'],
'uid' => $params['uid'],
];
//插入订单
DB::table('order')->insert($data);
//更新库存
DB::table('stock')->where('goods_id',$params['goods_id'])->decrement('num',$params['num']);
//提交事务
DB::commit();
return '抢到了';
}else{
//回滚事务
DB::rollBack();
return '暂无库存';
}
}

使用ab测试多次,没问题

ab -c 100 -n 100 "http://l8.com/2"

2.使用redis队列

先访问设置库存,再下单

//设置库存
public function index4s()
{
//模拟接受到的数据
$params = [
'goods_id' => 1,//商品id
'uid' => mt_rand(1,1000),//随机用户uid
'num' => 1,//购买的数量
];
$rdKey = 'goods_id_'.$params['goods_id'];
$num = DB::table('stock')->where('goods_id',$params['goods_id'])->first('num')->num;
for($i=0;$i<$num;$i++){
Redis::lpush($rdKey,1);
}
return '设置库存成功'.$num;
} //使用redis防止超卖
public function index4()
{
//模拟接受到的数据
$params = [
'goods_id' => 1,//商品id
'uid' => mt_rand(1,1000),//随机用户uid
'num' => 1,//购买的数量
];
$rdKey = 'goods_id_'.$params['goods_id']; $num = Redis::lpop($rdKey);
if($num!=1){
return '没货了';
}else{
$data = [
'order_sn' => date('YmdHis').mt_rand(1000,9999),
'goods_id' => $params['goods_id'],
'uid' => $params['uid'],
];
//插入订单
DB::table('order')->insert($data);
return '抢到了';
}
}

先访问,index4s ,

ab -c 1 -n 1 "http://l8.com/4s"

后使用ab测试多次,没问题

ab -c 100 -n 100 "http://l8.com/4"

3.使用异步队列

就是把下单扔到队列里面,前端轮询,用户排队等待结果

代码比较简陋,记得写日志哦!

ab压测详细使用

https://www.cnblogs.com/wangzhaobo/p/8296298.html

PHP防止订单超卖,秒杀,限购,PHP高并发防止超卖代码实践的更多相关文章

  1. 【转】从msql数据库处理高并发商品超卖

    今天王总又给我们上了一课,其实mysql处理高并发,防止库存超卖的问题,在去年的时候,王总已经提过:但是很可惜,即使当时大家都听懂了,但是在现实开发中,还是没这方面的意识.今天就我的一些理解,整理一下 ...

  2. Springboot分别使用乐观锁和分布式锁(基于redisson)完成高并发防超卖

    原文 :https://blog.csdn.net/tianyaleixiaowu/article/details/90036180 乐观锁 乐观锁就是在修改时,带上version版本号.这样如果试图 ...

  3. Java电商项目,秒杀,抢购等高并发场景的具体场景和一些概念以及处理思路

    这里我借鉴了网上其他大佬的观点: 一:高并发带来的挑战 原因:秒杀抢购会经常会带来每秒几万的高并发场景,为了更快的返回结果给用户. 吞吐量指标QPS(每秒处理请求数),假设一个业务请求响应耗时为100 ...

  4. Java Redis缓存穿透/缓存雪崩/缓存击穿,Redis分布式锁实现秒杀,限购等

    package com.example.redisdistlock.controller; import com.example.redisdistlock.util.RedisUtil; impor ...

  5. Springcloud 微服务 高并发(实战1):第1版秒杀

    疯狂创客圈 Java 高并发[ 亿级流量聊天室实战]实战系列之15 [博客园总入口 ] 前言 前言 疯狂创客圈(笔者尼恩创建的高并发研习社群)Springcloud 高并发系列文章,将为大家介绍三个版 ...

  6. [转] 基于MySQL的秒杀核心设计(减库存部分)-防超卖与高并发

    商品详情页面的静态化,varnish加速,秒杀商品库独立部署服务器这种就略过不讲了.只讨论库存部分的优化 mysql配置层面的优化可以参考我的这篇文章 <关于mysql innodb引擎性能优化 ...

  7. 下订单更新订单表然后减少库存表中的数据,出现库存超卖,使用数据库和redis坚决库存超卖的问题

    上面的代码更新库存的数据,存在多线程的问题,第一种方法使用synchronized关键字修饰的语句块代码,但是性能较低,并且还是存在问题的 在分布式的场景下,当前库存系统部署在多个tomcat上,即使 ...

  8. 使用Redis中间件解决商品秒杀活动中出现的超卖问题(使用Java多线程模拟高并发环境)

    一.引入Jedis依赖 可以新建Spring或Maven工程,在pom文件中引入Jedis依赖: <dependency> <groupId>redis.clients< ...

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

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

随机推荐

  1. 布局TabBar

    布局TabBar中的items Tabbar中应该有5个Item 主页/消息/发布按钮/发现/我 布局TabBar中的Items可以通过下面的方式 通过自定义TabBar的方式 多添加一个控制器,让中 ...

  2. 使用estimatedRowHeight的优缺点

    使用estimatedRowHeight的优缺点 1.优点 1> 可以降低tableView:heightForRowAtIndexPath:方法的调用频率 2> 将[计算cell高度的操 ...

  3. 软件版本GA、Beta、RC含义

    Alpha:是内部测试版,一般不向外部发布,会有很多Bug.一般只有测试人员使用.Beta:也是测试版,这个阶段的版本会一直加入新的功能.在Alpha版之后推出.RC:(Release Candida ...

  4. VC 为程序创建唯一标识

    转载请注明来源:https://www.cnblogs.com/hookjc/ 应用: 一台机器上只许运行一个客户端 同一个账号只允许登陆一个客户端 BOOl m_IsRun=false; HANDL ...

  5. Nodejs ORM框架Sequelize快速入门

    Nodejs ORM框架Sequelize快速入门 什么是ORM? 简单的讲就是对SQL查询语句的封装,让我们可以用OOP的方式操作数据库,优雅的生成安全.可维护的SQL代码.直观上,是一种Model ...

  6. DatabaseMetaData

    getColumns public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern ...

  7. [杭电新生赛]hgame-week1-web-wp

    hgame第一周总结 (官方wp更加简洁明了.直入主题,个人比较菜,所以过程繁琐 写好了一直没发qwq(就是懒(bushi) 一.Tetris plus! 题目里说玩到3000分就给flag,还真有点 ...

  8. Msi.h causes compilation error in vs2010

    创建一个Win32 Console工程ReadFromMSM,什么都不需要做. 在ReadFromMSM.cpp文件中引入头文件: #include <msi.h> 编译,会发现有成堆的错 ...

  9. sublime运行错误

      这是由于没有保存文档导致   说明: [Finished in 19.4s with exit code 1]-表示执行时间 [shell_cmd: python3 -u "/Volum ...

  10. Solution -「LOCAL」ZB 平衡树

    \(\mathcal{Description}\)   OurOJ.   维护一列二元组 \((a,b)\),给定初始 \(n\) 个元素,接下来 \(m\) 次操作: 在某个位置插入一个二元组: 翻 ...