在没有用Redisson时,用jmeter做压力测试时出现的问题。库存设定为50,用5个线程去测
测试代码
//秒杀活动
@GetMapping("buyItem")
public Object getUserInfoByUserId(@RequestParam(value = "itemId",required = true) long item){
RedissonRedis value = (RedissonRedis) RedisUtil.getValue(redisTemplate, CarownerhomeKeyName.buyShopItemInfo + item);
long count= Long.parseLong(value.getItemCount());
if (value==null ){
return "商品不存在";
}
System.out.println("当前商品"+item+"的redis库存"+count);
if (count > 0){
//减库操作
updateRedis(item);
System.out.println("购买商品后"+item+"的mysql库存"+redissonService.getById(item).getItemCount());
RedissonRedis value1 =(RedissonRedis) RedisUtil.getValue(redisTemplate, CarownerhomeKeyName.buyShopItemInfo + item);
System.out.println("购买商品后"+item+"的redis库存"+value1.getItemCount());
}
return "购买成功";
}
public void updateRedis(long item){
long countNew =0;
try {
RedissonRedis value =(RedissonRedis) RedisUtil.getValue(redisTemplate, CarownerhomeKeyName.buyShopItemInfo + item);
System.out.println("--------当前商品"+item+"的redis库存"+value.getItemCount());
long i= Long.parseLong(value.getItemCount());
if (value != null && i>0){
countNew=i-1;
}else {
throw new RRException("该商品库存不够了");
}
redissonService.updateById(item, String.valueOf(countNew));
updateDbRedisNoLock(item);
}catch (Exception e){
System.out.println(e.getMessage());
throw e;
}
压力测试显示成功
后台输出情况
数据库情况
根据后台输出情况,各个线程进来时拿到的库存都是50 ,就出现了问题。这里就需要到锁。
最简单的办法 是在方法上加上synchronized 关键字 给这个方法加上锁 让线程之间分开执行。
但是这个方法不能考虑锁住分布式的问题。当有布置多个服务器,有多个线程组同时压测时就有问题。
这里用到redisson 就能解决这个问题
//秒杀活动
@GetMapping("buyItem")
public Object getUserInfoByUserId(@RequestParam(value = "itemId",required = true) long item) throws Exception {
//创建锁
RReadWriteLock readWriteLock = redisson.getReadWriteLock(String.valueOf(item));
//创建写锁
RLock rLock = readWriteLock.writeLock();
//开启锁
rLock.lock();
try {
RedissonRedis value = (RedissonRedis) RedisUtil.getValue(redisTemplate, CarownerhomeKeyName.buyShopItemInfo + item);
long count= Long.parseLong(value.getItemCount());
if (value==null ){
return "商品不存在";
}
System.out.println("当前商品"+item+"的redis库存"+count);
if (count > 0){
//减库操作
updateRedis(item);
System.out.println("购买商品后"+item+"的mysql库存"+redissonService.getById(item).getItemCount());
RedissonRedis value1 =(RedissonRedis) RedisUtil.getValue(redisTemplate, CarownerhomeKeyName.buyShopItemInfo + item);
System.out.println("购买商品后"+item+"的redis库存"+value1.getItemCount());
}
return "购买成功";
}catch (Exception e){
System.out.println(e);
throw new Exception();
}finally {
//关闭锁
rLock.unlock();
}
}