Redis(二十二)-秒杀案例的基本实现以及用ab工具模拟并发
Posted 码农飞哥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis(二十二)-秒杀案例的基本实现以及用ab工具模拟并发相关的知识,希望对你有一定的参考价值。
您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦。
💪🏻 1. Python基础专栏,基础知识一网打尽,9.9元买不了吃亏,买不了上当。 Python从入门到精通
❤️ 2. Python爬虫专栏,系统性的学习爬虫的知识点。9.9元买不了吃亏,买不了上当 。python爬虫入门进阶
❤️ 3. Ceph实战,从原理到实战应有尽有。 Ceph实战
❤️ 4. Java高并发编程入门,打卡学习Java高并发。 Java高并发编程入门
😁 5. 社区逛一逛,周周有福利,周周有惊喜。码农飞哥社区,飞跃计划
全网同名【码农飞哥】欢迎关注,个人VX: wei158556
文章目录
简介
上一篇文章我们介绍了悲观锁和乐观锁,Redis(二十一)-Redis的事务冲突(悲观锁和乐观锁)。这篇文章我们接着来学习Redis,本文主要介绍如何通过Redis来实现秒杀,以及如何通过ab工具来模拟并发。
秒杀案例的基本实现
商品秒杀是电商系统中的一个常见场景,就是商家将拿出少量某商品以特价的方式,在有限的时间内进行销售。在秒杀的场景中需要注意的情况是:1. 商品不能超卖,2. 同一个人只能抢一次。所以,
- 秒杀的基本实现思路有如下七个步骤:
//uid 是用户ID
// prodid 是商品ID
public boolean doSeckill(String uid, String prodid)
// 1.uid和prodid非空判断
if (StringUtils.isAnyBlank(uid, prodid))
System.out.println("uid和prodid为空");
return false;
// 2.连接redis
Jedis jedis = new Jedis("127.0.0.1", 6379);
// 3.拼接key
// 3.1. 库存key
String skKey = "sk:" + prodid + ":qt";
// 3.2. 秒杀成功用户key
String userKey = "sk:" + prodid + ":user";
// 4.获取库存,如果库存null,秒杀还没有开始
String skValue = jedis.get(skKey);
if (skValue == null)
System.out.println("秒杀还没开始,请等待");
jedis.close();
return false;
// 5.判断用户是否重复操作
Boolean sismember = jedis.sismember(userKey, uid);
if (sismember)
System.out.println("该用户已经抢过一次,请勿重复抢购");
jedis.close();
return false;
// 6. 判断如果商品数量,库存数量小于1,秒杀结束
if (Integer.parseInt(skValue) <= 0)
System.out.println("该商品的库存不足,秒杀失败");
jedis.close();
return false;
// 7. 秒杀过程
// 7.1. 库存-1
jedis.decr(skKey);
// 7.2. 用户加入到set集合中
jedis.sadd(userKey, uid);
System.out.println("秒杀成功");
return true;
- 为了防止某个用户重复抢,所以需要将抢过的用户id放在set 这个数据类型中,在每次请求是需要判断该set中有没有该用户。
- 为了防止超卖的情况,所以,在每次请求之前都需要查看一下当前的商品数量,如果商品数量等于0则返回库存不足,用户成功抢到商品之后需要将库存-1。
- 定义的测试接口是:
@RequestMapping("/skill/do")
public boolean setandGetValue()
String prodid = "1010";
StringBuilder uidSB = new StringBuilder("");
for (int i = 0; i < 6; i++)
int nextInt = new Random().nextInt(10);
uidSB.append(nextInt);
boolean result = seckillService.doSeckill(uidSB.toString(), prodid);
return result;
- 在redis中设置秒杀商品的数量为10个。设置的命令是:
set sk:1010:qt 10
请求地址是:http://10.41.152.17:8080/seckill/skill/do。其中seckill是项目名。单个请求的测试结果如下图所示:
ab工具模拟并发
这里通过Linux的ab工具模拟并发测试,ab工具的安装使用非常简单。
安装ab工具
在联网的情况下只需要通过 yum install httpd-tools
命令即可安装ab工具。
安装完成之后通过ab --help
命令可以查看ab命令的各个参数的含义。
其中最常用的参数是:
-n 最大的请求数
-c 同时最大的并发数
-p postfile 指定post请求的参数
-T 指定请求的content-type
可以通过vim postfile
模拟表单提交参数,以&符号结尾,存放在当前目录,输入内容 prodid=1010&
(PS: 在本次测试中实际上没有到)
输入下面的测试命令测试一波,该命令指定了最大请求数是1000个,并发数是100个,10.41.152.17 是你本机的IP地址。
ab -n 1000 -c 100 -p postfile -T 'application/x-www-form-urlencoded' http://10.41.152.17:8080/seckill/skill/do
在测试之前依然通过set sk:1010:qt 10
命令设置10个秒杀商品qt。
执行结果如下三个图片所示:
从上述两个图片可以看出此基本实现过程有如下几个问题:
- 前面的线程都提示
商品库存不足,秒杀失败
,后面的线程还能提示秒杀成功
,检查商品的数量发现商品数量为-6,也就是说出现了超卖的情况。
- 后面的jedis客户端请求会出现
connect timed out
连接超时的情况。
这两个问题的解决方案会在后续的文章中详细介绍。
总结
本文通过jedis客户端简单实现了秒杀的案例,并通过ab工具模拟了并发测试。但是,由于代码设计考虑不周,会出现超卖以及jedis客户端会出现连接超时的情况。
以上是关于Redis(二十二)-秒杀案例的基本实现以及用ab工具模拟并发的主要内容,如果未能解决你的问题,请参考以下文章