zoukankan      html  css  js  c++  java
  • 使用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
  • 相关阅读:
    守护进程-锁-队列(生产者消费者模型)
    正则表达式不包含某个字符串写法
    正则表达式匹配不包含某些字符串的技巧
    08.参数估计_点估计
    07.编程理解中心极限定理
    05.编程理解小数和大数定律
    03.描述性统计代码
    02.描述统计 (descriptive statistics)
    oracle之三手工不完全恢复
    oracle之三手工完全恢复
  • 原文地址:https://www.cnblogs.com/meijsuger/p/11987287.html
Copyright © 2011-2022 走看看