使用redisson做redis分布式锁

 

redisson分布式锁

思路:使用spring的切面来切入需要加锁执行的操作或者方法,在调用方法前由切面捕获,然后通过方法的注解获取具体执行锁的参数,根据参数尝试取锁。持有锁以后执行方法,待方法执行完毕或持有锁时间超时时释放锁。

如果有异常根据情况释放锁或者执行后置操作。

 

 

锁:

/**
 * @author Zhang Qiang
 * @date 2019/10/28 10:04
 */
@Data
@AllArgsConstructor
@Builder(toBuilder = true)
public class RedisLock {
    private String key;
    private String value;
}
View Code

 

## ReLock注解类

标明此注解为使用redis锁。通过切点获取需要使用锁的操作

/**
 * @author Zhang Qiang
 * @date 2019/10/28 11:49
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ReLock {
   /**
    * key
    */
    String key() default "";
    /**
     * 是否循环获取锁
     *
     */
    boolean isHold() default true;
    /**
     * 尝试加锁等待超时时间
     */
    long waitTime() default 300 * 1000L;
    /**
     * 最长持锁时间,到期自动解锁
     */
    long leaseTime() default 300 * 1000L;
    /**
     * 时间格式,默认ms
     */
    TimeUnit timeUnit() default TimeUnit.MICROSECONDS;
}
View Code

 

具体操作类:

/**
 * @author Zhang Qiang
 * @date 2019/10/28 14:11
 */
@Slf4j
@Component
public class RedissonLockHandler {

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 尝试加锁等待超时时间
     */
    private final static long LOCK_TRY_WAIT = 5 * 1000L;
    /**
     * 持锁时间,防止死锁
     */
    private final static long LOCK_EXPIRE = 10 * 1000L;

    public RLock getRLock(String key){
        return redissonClient.getLock(key);
    }

    public boolean tryLock0(String key) {
        RLock rLock = redissonClient.getLock(key);
        return rLock.tryLock();
    }

    public boolean tryLock(String key) throws InterruptedException{
        return tryLock(key, LOCK_TRY_WAIT, LOCK_EXPIRE);
    }

    public boolean tryLock(String key, long waitTime, long leaseTime) throws InterruptedException {
        return tryLock(key, LOCK_TRY_WAIT, LOCK_EXPIRE, TimeUnit.MILLISECONDS);
    }

    /**
    * @param key 锁
    * @param waitTime 等待时间
    * @param leaseTime 持有锁时间
    * @param unit 单位
    * @return boolean
    */
    public boolean tryLock(String key, long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
        RLock rLock = redissonClient.getLock(key);
        return rLock.tryLock(waitTime, leaseTime, unit);
    }

    public void unLock(String key) {
        RLock rLock = redissonClient.getLock(key);
        unLock(rLock);
    }

    public void unLock(RLock rLock){
        if (rLock != null && rLock.isLocked()){
            rLock.unlock();
        }
    }

}
View Code

 

实现切面:

/**
 * 定时任务
 * 加锁执行
 * @author Zhang Qiang
 * @date 2019/10/28 16:24
 */
@Slf4j
@Aspect
@Order(0)
@Component
public class RedissonAspect {

    @Autowired
    RedissonLockHandler redissonLockHandler;

    @Pointcut("execution(public * com.qulv.vdn.product.service.impl.ProductTimedTaskServiceImpl.*(..))")
    public void redisRLockPointCut(){
    }

    @Pointcut("execution(public * com.qulv.vdn.product.service.impl.SyncUserInfoByFailed.*(..))")
    public void redisRLockSyncUserInfoByFailedPointCut(){
    }

    @Around("redisRLockPointCut() || redisRLockSyncUserInfoByFailedPointCut()")
    public Object timeTaskAround(ProceedingJoinPoint joinPoint){
        Object rollBack = null;
        boolean isLocked = false;
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        if (method.isAnnotationPresent(ReLock.class)){
            ReLock reLock = method.getAnnotation(ReLock.class);
            String key = reLock.key();
            if ("".equals(key)) { key = getLockKey(methodSignature); }
            RLock rLock = redissonLockHandler.getRLock(key);
            if (rLock != null){
                try {
                    if (reLock.isHold()){
                        isLocked = redissonLockHandler.tryLock(key, reLock.waitTime(), reLock.leaseTime(), reLock.timeUnit());
                    } else {
                        isLocked = redissonLockHandler.tryLock0(key);
                    }
                    if (isLocked){
                        log.info(" =====  执行定时任务  ===== :{} ", method.getName() );
                        rollBack = joinPoint.proceed();
                    } else {
                        log.warn("========== 获取锁失败,未执行 ============ : {} ", method.getName());
                    }
                } catch (Throwable throwable) {
                    log.warn(" 获取 redisRLock 异常中断 : {}" , throwable.getMessage());
                } finally {
                    redissonLockHandler.unLock(rLock);
                }
            }
        }
        return rollBack;
    }

    private String getLockKey(MethodSignature methodSignature){
        return methodSignature.getMethod().getName();
    }

}
View Code

 

 

posted on 2019-12-05 09:51  GhostSugar  阅读(1023)  评论(0编辑  收藏  举报