1.导入需要的包
<!-- hutool -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>25.1-jre</version>
</dependency>
2.代码段
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.feifan.common.core.domain.R;
import com.feifan.common.redis.service.RedisService;
import com.feifan.educate.service.apiService.IEducateQuestionService;
import com.google.common.collect.Interner;
import com.google.common.collect.Interners;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("test")
public class TestJMeterController {
//需要使用key作为互斥锁,所以使用Interners将key添加到常量池中,谷歌包下的
static final Interner<String> pool = Interners.newWeakInterner();
@Resource
private IEducateQuestionService questionService;
@Resource
private RedisService redisService; //封装的redis工具
@GetMapping("jmeterTest")
public R jmeterTest(@RequestParam Integer userId){
String now = DateUtil.now();
//将key作为互斥锁
synchronized (pool.intern("jmeter" + userId)){
//从redis中查询用户是否已经抢购成功,如果从数据库中查询会执行的很慢
if (null != redisService.getCacheObject("jorder:userId"+userId) ){
return R.fail("您已强够成功不能再次抢购");
}
String result = "";
Integer count = Integer.parseInt(redisService.getCacheObject("jmeter").toString());//查询剩余库存
System.out.println("剩余库存:"+count);
if (count > 0){ // 库存大于0,可以抢购
result = "抢购成功:"+count;
System.out.println("用户:"+userId+":抢购成功");
redisService.setCacheObject("jmeter",count-1);//减库存
Integer inventory = Integer.parseInt(redisService.getCacheObject("inventory").toString()); //查询已抢购的数量
redisService.setCacheObject("inventory",inventory+1); //抢购数量+1
redisService.setCacheObject("jorder:userId"+userId,count);//保存用户抢购成功数据到redis
questionService.addOrder(userId, IdUtil.simpleUUID()); //保存用户下单数据到数据库
}else {
result = "抢购失败";
}
return R.ok(result);
}
}
}
3.这里我使用的是jmeter压力测试,同一个用户只能下单一次
4.redis中的库存初始数据设置为10,已购买数量为0
5. 开始测试
用同一个用户执行了一万次后我们的redis库存变成了9,已购买数量为1,而数据库中也只有一个用户的购买信息,仍然是只有一单
库存变成了9
已购买数量为1
用户信息redis中,userId为10的用户有了抢购记录
mysql数据库中用户数据,userid为10也有一条记录
这样就实现了秒杀的功能,没有出现超卖,也实现了一个用户只能够抢购一次的功能