一、使用redis的事务解决秒杀问题,但是会产生库存遗留问题
二、使用lua脚本解决秒杀问题
0、使用lua脚本的优势

1、具体使用的service层代码
package com.bear.service;
import com.bear.config.JedisPoolUtil;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import java.io.IOException;
@Service
public class SewckillServiceTwo {
String secKillScript ="local userid=KEYS[1];\r\n" +
"local prodid=KEYS[2];\r\n" +
"local qtkey='sk:'..prodid..\":qt\";\r\n" +
"local usersKey='sk:'..prodid..\":usr\";\r\n" +
"local userExists=redis.call(\"sismember\",usersKey,userid);\r\n" +
"if tonumber(userExists)==1 then \r\n" +
" return 2;\r\n" +
"end\r\n" +
"local num= redis.call(\"get\" ,qtkey);\r\n" +
"if tonumber(num)<=0 then \r\n" +
" return 0;\r\n" +
"else \r\n" +
" redis.call(\"decr\",qtkey);\r\n" +
" redis.call(\"sadd\",usersKey,userid);\r\n" +
"end\r\n" +
"return 1" ;
public boolean doSecKill(String prodid,String uid) throws IOException {
JedisPool jedispool = JedisPoolUtil.getJedisPoolInstance();
Jedis jedis=jedispool.getResource();
String sha1= jedis.scriptLoad(secKillScript);
Object result= jedis.evalsha(sha1, 2, uid,prodid);
String reString=String.valueOf(result);
if ("0".equals( reString ) ) {
System.err.println("已抢空!!");
}else if("1".equals( reString ) ) {
System.out.println("抢购成功!!!!");
}else if("2".equals( reString ) ) {
System.err.println("该用户已抢过!!");
}else{
System.err.println("抢购异常!!");
}
jedis.close();
return true;
}
}
2、controller层
@GetMapping("/seckill/test")
public Boolean seckillTest() throws IOException {
return sewckillServiceTwo.doSecKill("1001", Long.toString(System.currentTimeMillis()));
}
三、使用锁的方式解决秒杀问题(这里在java里面使用的方式是redisTemplate提供的操作redis锁的方式)
@GetMapping("/testLock")
public void testLock(@RequestParam("pid") String pid, @RequestParam("userid") String userid){
String uuid = UUID.randomUUID().toString();
Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", userid, 5, TimeUnit.SECONDS);
if(lock){
String user = Long.toString(System.currentTimeMillis());
Object value = redisTemplate.opsForValue().get("sk:"+ pid +":count");
if(StringUtils.isEmpty(value)){
System.err.printf("秒杀未开始,敬请期待");
return;
}
if((int)value == 0){
System.err.println("秒杀已经结束");
return;
}
Set members = redisTemplate.opsForSet().members("sk:" + pid + ":user");
if(members.contains(userid)) {
System.err.println("已经参与秒杀,请勿重复参与!");
return;
}
redisTemplate.opsForValue().set("sk:"+ pid +":count", (int)value -1);
redisTemplate.opsForSet().add("sk:"+ pid +":user", userid);
System.out.println("秒杀成功!");
String lock1 = redisTemplate.opsForValue().get("lock").toString();
if(uuid.equals(lock1)){
redisTemplate.delete("lock");
}
}else{
try {
Thread.sleep(100);
testLock(pid, userid);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
四、使用redission操作redis,解决秒杀问题(公司使用的是这种方式,只需要将redisTemplate换成redission即可)