Redis分布式锁实现

应用场景

并发情况下为了保证资源不被相互争夺,每次请求都对数据加锁

原生实现
/**
 * 扣减库存
 * @return
 */
public String deductStock(){
//定义锁
String lockKey = "lockKey";
//设置锁ID 确保唯一
String cid = UUID.randomUUID().toString();
//添加一把实效30秒的锁 如果存在就不操作
Boolean result = redisTemplate.opsForValue().setIfAbsent(lockKey,cid,10, TimeUnit.SECONDS);
if(!result){
    return "锁被占用!";
}

 try {
      //模拟业务操作
     int stock = Integer.parseInt(redisTemplate.opsForValue().get("stock").toString());
     if(stock>0){
         System.out.println("当前库存:"+stock);
         stock = stock-1;
         redisTemplate.opsForValue().set("stock",stock);
     }else{
         System.out.println("库存不足:"+stock);
         return "error";
     }
    }catch (Exception e){
        e.printStackTrace();
    }finally {
     //不管怎么样最后程序最后都要删除自己的
        if(cid.equals(redisTemplate.opsForValue().get(lockKey))){
         redisTemplate.delete(lockKey);
        }
 }
     return "success";
}

以上方法基本情况下使用没问题,但是在特殊情况下, 锁的过期时间永远无法预估。
如果业务实现操作时间过长,或者集群情况下切换服务的时候 会导致服务无法使用 必须等到锁失效。

使用Redisson更方便的实现
public String deductStock2(){
    String lockKey = "lockKey";
    //获取redis锁
    RLock redissonLock =  redisson.getLock(lockKey);
    try {
        //加锁
        redissonLock.lock();
        //模拟业务操作
        int stock = Integer.parseInt(redisTemplate.opsForValue().get("stock").toString());
        if(stock>0){
            System.out.println("当前库存:"+stock);
            stock = stock-1;
            redisTemplate.opsForValue().set("stock",stock);
        }else{
            System.out.println("库存不足:"+stock);
            return "error";
        }
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        //释放锁
        redissonLock.unlock();
    }
    return "success";
}

jar依赖

     
            org.springframework.boot
            spring-boot-starter-data-redis
        
        
            org.redisson
            redisson
            3.5.0
        

@Bean
public RedissonClient redisson(){
    Config  config = new Config();
    config.useSingleServer().setAddress("redis://127.0.0.1:6379")
            .setDatabase(9)
            .setPassword("123456");
    return  Redisson.create(config);
}

你可能感兴趣的:(Redis分布式锁实现)