PHP防止订单超卖,秒杀,限购,PHP高并发防止超卖代码实践
建表
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高并发防止超卖代码实践的更多相关文章
- 【转】从msql数据库处理高并发商品超卖
今天王总又给我们上了一课,其实mysql处理高并发,防止库存超卖的问题,在去年的时候,王总已经提过:但是很可惜,即使当时大家都听懂了,但是在现实开发中,还是没这方面的意识.今天就我的一些理解,整理一下 ...
- Springboot分别使用乐观锁和分布式锁(基于redisson)完成高并发防超卖
原文 :https://blog.csdn.net/tianyaleixiaowu/article/details/90036180 乐观锁 乐观锁就是在修改时,带上version版本号.这样如果试图 ...
- Java电商项目,秒杀,抢购等高并发场景的具体场景和一些概念以及处理思路
这里我借鉴了网上其他大佬的观点: 一:高并发带来的挑战 原因:秒杀抢购会经常会带来每秒几万的高并发场景,为了更快的返回结果给用户. 吞吐量指标QPS(每秒处理请求数),假设一个业务请求响应耗时为100 ...
- Java Redis缓存穿透/缓存雪崩/缓存击穿,Redis分布式锁实现秒杀,限购等
package com.example.redisdistlock.controller; import com.example.redisdistlock.util.RedisUtil; impor ...
- Springcloud 微服务 高并发(实战1):第1版秒杀
疯狂创客圈 Java 高并发[ 亿级流量聊天室实战]实战系列之15 [博客园总入口 ] 前言 前言 疯狂创客圈(笔者尼恩创建的高并发研习社群)Springcloud 高并发系列文章,将为大家介绍三个版 ...
- [转] 基于MySQL的秒杀核心设计(减库存部分)-防超卖与高并发
商品详情页面的静态化,varnish加速,秒杀商品库独立部署服务器这种就略过不讲了.只讨论库存部分的优化 mysql配置层面的优化可以参考我的这篇文章 <关于mysql innodb引擎性能优化 ...
- 下订单更新订单表然后减少库存表中的数据,出现库存超卖,使用数据库和redis坚决库存超卖的问题
上面的代码更新库存的数据,存在多线程的问题,第一种方法使用synchronized关键字修饰的语句块代码,但是性能较低,并且还是存在问题的 在分布式的场景下,当前库存系统部署在多个tomcat上,即使 ...
- 使用Redis中间件解决商品秒杀活动中出现的超卖问题(使用Java多线程模拟高并发环境)
一.引入Jedis依赖 可以新建Spring或Maven工程,在pom文件中引入Jedis依赖: <dependency> <groupId>redis.clients< ...
- mysql处理高并发,防止库存超卖
先来就库存超卖的问题作描述:一般电子商务网站都会遇到如团购.秒杀.特价之类的活动,而这样的活动有一个共同的特点就是访问量激增.上千甚至上万人抢购一个商品.然而,作为活动商品,库存肯定是很有限的,如何控 ...
随机推荐
- JAVA中获取不同系统的换行符和获取系统路径路径分割符
简介 JAVA具有多平台特征,一次开发,多平台运行,主要依据JVM,但是不同的操作系统中换行符和分割符不同,故需要根据不同的操作系统去获取不同的符号. JAVA代码 @Test public void ...
- js中数组的添加和移除
1.引入js文件 <script src="../plugins/jQuery/jquery-2.2.3.min.js"></script>2.HTML中代 ...
- C3P0数据库连接池数据库插入中文乱码问题解决
问题描述 近期修改一个学生信息管理的JavaWeb项目,其数据库连接池使用了C3P0.在实际测试时,发现在学生信息模块添加中文学生信息会在数据库(MySQL)出现中文乱码问题. 如图所示: 问题分析 ...
- Git提示“warning: LF will be replaced by CRLF”
感谢原文作者:萌新李同学(李俊德-大连理工大学) 原文链接:https://blog.csdn.net/wq6ylg08/article/details/88761581 问题描述 windows平台 ...
- 入门 - k8s滚动更新部署中的镜像版本 (七)
目标 使用 kubectl 执行 Rolling Update(滚动更新) 更新应用程序 用户期望应用程序始终可用,为此开发者/运维者在更新应用程序时要分多次完成.在 Kubernetes 中,这是通 ...
- web容器、sevlet容器、spring容器、springmvc容器之间的关系
原文链接:http://www.cnblogs.com/jieerma666/p/10805966.html https://blog.csdn.net/zhanglf02/article/detai ...
- https校验问题
一般会报SSL问题:解决办法参考 http://blog.csdn.net/a506681571/article/details/78284589 # 设置未经允许验证的SSL方法,只需运行一次便可 ...
- 06 前端之Bootstrap框架
目录 前端之Bootstrap框架 一.简介 二.引入方式 本地引入(最完整的) CDN引入 三.布局容器 四.栅格系统 五.列偏移 六.表格与表单 6.1表格 6.2表单form 七.按钮 预定义样 ...
- Solution -「CF 908D」New Year&Arbitrary Arrangement
\(\mathcal{Description}\) Link. 给定 \(n,p_a,p_b\),初始有一个空串,每次操作有 \(\frac{p_a}{p_a+p_b}\) 的概率在其后添加字 ...
- Dubbo源码剖析六之SPI扩展点的实现之getExtension
上文Dubbo源码剖析六之SPI扩展点的实现之getExtensionLoader - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)中分析了getExtensionLoader,本文继续分 ...