现在有1个秒杀的功能,1个原来价值5000元的手机现在搞活动,降价到1块钱,做秒杀活动。库存就10个,假设有10000人抢购。
目前逻辑是:抢到了商品库存就减1,然后把用户id加入到秒杀成功者清单中
模拟我们使用工具 ab 模拟测试:
CentOS6 默认安装
CentOS7 需要手动安装: yum install httpd-tools
执行以下命令
ab -n 2000 -c 200 -k -p ~/postfile -T application/x-www-form-urlencoded
postfile是1个我们自定义的文件,内容如下
prodid=0101& # 以 & 号结尾,存放当前目录
秒杀的结果如下图所示:
明明10个名额抢完了,还提示秒杀成功,且redis中库存显示不为0
利用乐观锁淘汰用户,解决超卖问题。
具体代码如下:
public class SecKill_redis {
public static void main(String[] args) {
Jedis jedis =new Jedis("192.168.44.168",6379);
System.out.println(jedis.ping());
jedis.close();
}
//秒杀过程
public static boolean doSecKill(String uid,String prodid) throws IOException {
//1 uid和prodid非空判断
if(uid == null || prodid == null) {
return false;
}
//2 连接redis
//Jedis jedis = new Jedis("192.168.44.168",6379);
//通过连接池得到jedis对象
JedisPool jedisPoolInstance = JedisPoolUtil.getJedisPoolInstance();
Jedis jedis = jedisPoolInstance.getResource();
//3 拼接key
// 3.1 库存key
String kcKey = "sk:"+prodid+":qt";
// 3.2 秒杀成功用户key
String userKey = "sk:"+prodid+":user";
//监视库存
jedis.watch(kcKey);
//4 获取库存,如果库存null,秒杀还没有开始
String kc = jedis.get(kcKey);
if(kc == null) {
System.out.println("秒杀还没有开始,请等待");
jedis.close();
return false;
}
// 5 判断用户是否重复秒杀操作
if(jedis.sismember(userKey, uid)) {
System.out.println("已经秒杀成功了,不能重复秒杀");
jedis.close();
return false;
}
//6 判断如果商品数量,库存数量小于1,秒杀结束
if(Integer.parseInt(kc)<=0) {
System.out.println("秒杀已经结束了");
jedis.close();
return false;
}
//7 秒杀过程
//使用事务
Transaction multi = jedis.multi();
//组队操作
multi.decr(kcKey);
multi.sadd(userKey,uid);
//执行
List<Object> results = multi.exec();
if(results == null || results.size()==0) {
System.out.println("秒杀失败了....");
jedis.close();
return false;
}
//7.1 库存-1
//jedis.decr(kcKey);
//7.2 把秒杀成功用户添加清单里面
//jedis.sadd(userKey,uid);
System.out.println("秒杀成功了..");
jedis.close();
return true;
}
}
测试结果
当我们加大并发量再去测试时,可能会出现连接超时的问题
已经秒光,可是还有库存,原因:乐观锁导致很多请求都失败。先点的没秒到,后点的可能秒到了。
解决库存遗留问题,我们首先想到使用悲观锁,但在redis中不能直接使用悲观锁,所以使用LUA脚本
LUA 脚本在 Redis 中的优势
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://www.cnblogs.com/jiakecong/p/17156748.html
内容来源于网络,如有侵权,请联系作者删除!