使用Redis实现秒杀业务
【摘要】 使用Redis实现秒杀业务
使用redis的事务,商品数减减,用户信息使用Set集合
实现方式一
package com.promsing.jedis.seckill;
import redis.clients.jedis.Jedis;
import java.io.IOException;
/**
* 模拟秒杀,未使用事务
*
* @author Promsing(张有博)
* @version 1.0.0
* @since 2022/5/7 - 17:13
*/
public class SeckillJedisV1 {
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 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("127.0.0.1", 6379);
//通过连接池得到jedis对象
//3 拼接key
// 3.1 库存key
String kcKey = "sk:"+prodid+":qt";
// 3.2 秒杀成功用户key
String userKey = "sk:"+prodid+":user";
//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 秒杀过程
//7.1 库存-1
jedis.decr(kcKey);
// 7.2 把秒杀成功用户添加清单里面
jedis.sadd(userKey,uid);
System.out.println("秒杀成功了..");
jedis.close();
return true;
}
}

并发情况下存在:
1.超卖问题:,活动结束了,还能卖。
没有事务,两者同时拿到,都会售卖。
2.超时问题:redis连接数被占满,连接超时。
实现方式二 - 解决超卖超时
使用redis连接池
节省每次连接redis服务带来的消耗,把连接好的实例反复利用。通过参数管理连接的行为
使用乐观锁+redis事务
import com.promsing.jedis.utils.JedisPoolUtil;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Transaction;
import java.io.IOException;
import java.util.List;
/**
* 秒杀,解决超卖、超时
*
* @author Promsing(张有博)
* @version 1.0.0
* @since 2022/5/8 - 14:05
*/
public class SeckillJedisV2 {
//秒杀过程
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("127.0.0.1", 6379);
//通过连接池得到jedis对象
JedisPool jedisPool = JedisPoolUtil.getJedisPoolInstance();
Jedis jedis = jedisPool.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();
//库存-1
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;
}
System.out.println("秒杀成功了..");
jedis.close();
return true;
}
}
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* Jedis连接池
*
* @author Promsing(张有博)
* @version 1.0.0
* @since 2022/5/8 - 14:08
*/
public class JedisPoolUtil {
private static volatile JedisPool jedisPool = null;
private JedisPoolUtil() {
}
public static JedisPool getJedisPoolInstance() {
if (null == jedisPool) {
synchronized (JedisPoolUtil.class) {
if (null == jedisPool) {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(200);
poolConfig.setMaxIdle(32);
poolConfig.setMaxWaitMillis(100*1000);
poolConfig.setBlockWhenExhausted(true);
poolConfig.setTestOnBorrow(true); // ping PONG
jedisPool = new JedisPool(poolConfig, "127.0.0.1", 6379, 60000 );
}
}
}
return jedisPool;
}
public static void release(JedisPool jedisPool, Jedis jedis) {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
}
实现方式三 -解决库存遗留
出现原因:当有一个人修改了版本号,其他所有人都事务失败。因为你其余人都会核对版本号,当不一致,会事务失败
使用LUA脚本
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)