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处理高并发,防止库存超卖
先来就库存超卖的问题作描述:一般电子商务网站都会遇到如团购.秒杀.特价之类的活动,而这样的活动有一个共同的特点就是访问量激增.上千甚至上万人抢购一个商品.然而,作为活动商品,库存肯定是很有限的,如何控 ...
随机推荐
- 【转】Python中自定义可迭代对象
python 中内置的可迭代的对象有 list.tuple.set.dict 等,那么我们自己怎么定义一个可迭代的对象呢?先来段代码吧 import re import reprlib RE_WORD ...
- 【转】Python 并行分布式框架 Celery
原文链接:https://blog.csdn.net/freeking101/article/details/74707619 Celery 官网:http://www.celeryproject.o ...
- 用maven在MANIFEST.MF文件中的Class-Path中增加当前目录(.)
Xml代码 <configuration> <archive> <manifest> <mainClass>com.dongwei.test.Main& ...
- Redis 源码简洁剖析 10 - aeEventLoop 及事件
aeEventLoop IO 事件处理 IO 事件创建 读事件处理 写事件处理 时间事件处理 时间事件定义 时间事件创建 时间事件回调函数 时间事件的触发处理 参考链接 Redis 源码简洁剖析系列 ...
- YOLOv5模型训练及检测
一.为什么使用YOLOv5 二.软件工具 2.1 Anaconda https://www.anaconda.com/products/individual 2.2 PyCharm https://w ...
- ssh一段时间无操作后自动断开连接(假死)问题
平时使用ssh远程服务器的时候(注:远程虚拟机一般不会有这个问题),一段时间没有操作,ssh连接就会处于假死状态,以至于需要重新进行ssh连接,不管你用的什么远程工具都会出现这个问题,那么通过心跳检测 ...
- SpringCloud微服务实战——搭建企业级开发框架(三十六):使用Spring Cloud Stream实现可灵活配置消息中间件的功能
在以往消息队列的使用中,我们通常使用集成消息中间件开源包来实现对应功能,而消息中间件的实现又有多种,比如目前比较主流的ActiveMQ.RocketMQ.RabbitMQ.Kafka,Stream ...
- Solution -「多校联训」自动机
\(\mathcal{Description}\) Link. 有一个状态集为 \(V\) 的自动机,状态接收 (, ) 和 _(空格) 三种字符,分别编号为 \(0,1,2\),状态 \(u ...
- Git简单介绍以及使用入门
Git Git:分布式版本控制系统, 此外还有 SVN (集中式版本控制系统) 下载地址(阿里云镜像) :CNPM Binaries Mirror (npmmirror.com) Git Bash : ...
- mysql 查询附近N公里内数据
mysql 查询一个地点(经纬度) 附近N公里内的数据.(根据一个地点的经纬度查询这个地点方圆几公里内的数据)1.创建测试表 CREATE TABLE `location` ( `id` int(10 ...