建表

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. 「Ynoi2018」未来日记

    「Ynoi2018」未来日记 区间x->y,kth值... 不管了,先序列分块... 查询 第k值,假定知道每个数的权值,对值域分块. 对于整块,维护前\(i\)个块当中,值域在\(j\)块里以 ...

  2. 2020-11-21 f

    题意:给定一个长度为 \(n\) 的序列 \(A\),\(A_i \in [0, 2 ^ k)\).定义 \(f(x)\) 为 \(A_1\) ^ \(x\),\(A_2\) ^ \(x \cdots ...

  3. Win10 提示凭证不工作问题

    感谢大佬:https://cloud.tencent.com/developer/article/1337081 在公司局域网远程自己计算机的时候,突然无法远程了,提示"您的凭据不工作 之前 ...

  4. Core Animation的使用步骤

  5. js trim()方法

    从字符串中移除前导空格.尾随空格和行终止符. 语法 stringObj.trim() 参数 stringObj 必选.String 对象或字符串.trim 方法不修改该字符串. 返回值 已移除前导空格 ...

  6. kebernet--新手填坑

    1.安装好kubernet之后,新建rc后,里面的容器一直ImagePullBackOff ,镜像无法拉取: ----需要配置docker镜像为国内镜像,记得在各个Node上都要配置!!! vim / ...

  7. win8.1/2012R2上面安装flash debugger

    1.开启windows桌面体验 a. Launch Power Shell b. Run command "add-WindowsFeature Desktop-Experience&quo ...

  8. 用Java中的File类模拟实现对系统文件的增删改查效果

    码字不易,三连支持一波吧 IO操作向来是各大语言的热区,而对文件的操作也是重中之重. 那么在Java中也给我们提供了很多关于文件操作的类.今天我就用一个比较基本的File类来模拟实现对文件的增删改查效 ...

  9. Linux基础:子网划分

    一.ip地址基本知识 1.1 ip地址的结构和分类 1.2 特殊ip地址 1.3 子网掩码 1.4 ip地址申请 二.子网划分 2.1 子网划分概念 2.2 c类子网划分初探 2.3 子网划分步骤 2 ...

  10. DevOpts 前端开发和 Spug

    DevOpts 前端开发和 Spug 朋友新工作是进行 DevOpts 前端开发,涉及 Spug. DevOps 是什么 DevOps 是一种思想.用于促进开发和运维之间的沟通.协作或整合. Tip: ...