引入依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.2.0</version>
</dependency>
秒杀分析
- 定义缓存key
- 获取库存,如果库存为null,返回未开始
- 判断用书是否重复秒杀操作
- 判断如果商品数量库存小于1,秒杀结束
- 秒杀过程 ,1、存在减1
秒杀代码
package com.example.linqy.redis.config;
import redis.clients.jedis.Jedis;
/**
* @author linqy
* @version 1.0.0
* @ClassName SeckillDemo.java
* @Description
* @createTime 2024年01月13日 18:19:00
*/
public class SeckillDemo {
public static void seCcKill(String userid,String prodid) {
Jedis jedis=new Jedis("127.0.0.1",6379);
//定义缓存key
String ckKey="ck:"+prodid+":qt";
String userKey="sp:"+prodid+":user";
//获取库存,如果库存为null,返回未开始
String ck=jedis.get(ckKey);
if (ck==null){
System.out.println("秒杀还未开始");
jedis.close();
return;
}
//判断用书是否重复秒杀操作
//判断集合 ***<key>*** 是否为含有该 ***<value>*** 值,有返回 1,没有返回 0
if (jedis.sismember(userKey,userid)){
System.out.println("秒杀成功,不能重复秒杀");
jedis.close();
return;
}
//判断如果商品数量库存小于1,秒杀结束
if (Integer.parseInt(ck)<=0){
System.out.println("秒杀已经结束");
jedis.close();
return;
}
//秒杀过程 ,1、存在减1
jedis.decr(ckKey);
jedis.sadd(userKey,userid);
System.out.println("秒杀成功");
return;
}
}
存在超卖问题
以上代码会存在两处问题
- 并发的时候会有链接超时问题
- 会存在超卖问题
解决超卖问题
- 采用连接池解决链接超时问题
- -采用redis的事务来解决超卖问题
- 监听库存 String watch = jedis.watch(ckKey);
- 使用事务 Transaction multi = jedis.multi();
- 组队操作 multi.decr(ckKey); multi.sadd(userKey,userid);
- 执行 List exec = multi.exec();
- 改造后代码
package com.example.linqy.redis.config; import redis.clients.jedis.Jedis; import redis.clients.jedis.Transaction; import java.util.List; /** * @author linqy * @version 1.0.0 * @ClassName SeckillDemo.java * @Description * @createTime 2024年01月13日 18:19:00 */ public class SeckillDemo { public static void seCcKill(String userid,String prodid) { Jedis jedis=new Jedis("127.0.0.1",6379); //定义缓存key String ckKey="ck:"+prodid+":qt"; String userKey="sp:"+prodid+":user"; //监听库存 String watch = jedis.watch(ckKey); //获取库存,如果库存为null,返回未开始 String ck=jedis.get(ckKey); if (ck==null){ System.out.println("秒杀还未开始"); jedis.close(); return; } //判断用书是否重复秒杀操作 //判断集合 ***<key>*** 是否为含有该 ***<value>*** 值,有返回 1,没有返回 0 if (jedis.sismember(userKey,userid)){ System.out.println("秒杀成功,不能重复秒杀"); jedis.close(); return; } //判断如果商品数量库存小于1,秒杀结束 if (Integer.parseInt(ck)<=0){ System.out.println("秒杀已经结束"); jedis.close(); return; } //秒杀过程 // 使用事务 Transaction multi = jedis.multi(); //组对操作 multi.decr(ckKey); multi.sadd(userKey,userid); //执行 List<Object> exec = multi.exec(); if (exec==null||exec.size()==0){ System.out.println("秒杀结束"); jedis.close(); return; } } }引入redis的事务会存在库存遗留问题
解决办法可以利用redis的lau语言