zoukankan      html  css  js  c++  java
  • 分布式锁,springBoot 定时任务@Scheduleder

    //声明注解

    import java.lang.annotation.*;
    import java.util.concurrent.TimeUnit;
    
    /**
     * @ClassName RedisLock
     * @Author lvhoushuai(tsxylhs @ outlook.com)
     * @Date 2020-08-25
     **/
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD})
    @Documented
    public @interface RedisLock {
        String lockPrefix() default "";
        String lockKey() default "";
        long timeOut() default 5;
        TimeUnit timeUnit() default TimeUnit.SECONDS;
    }

    //注解实现

    import org.apache.commons.lang3.StringUtils;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @ClassName RedisLockAspect
     * @Author lvhoushuai(tsxylhs @ outlook.com)
     * @Date 2020-08-25
     * @Description 拦截器实现
     **/
    @Aspect
    @Component
    public class RedisLockAspect {
        private static final Integer Max_RETRY_COUNT=3;
        private static final String LOCK_PRE_FIX="lockPreFix";
        private static final String LOCK_KEY = "lockKey";
        private static final String TIME_OUT = "timeOut";
        private static final int PROTECT_TIME = 2 << 11;//4096
        private static final Logger log= LoggerFactory.getLogger(RedisLock.class);
       @Autowired
        private CommonRedistHelper commonRedistHelper;
       @Pointcut("@annotation(com.sensetime.finance.auditlogweb.aop.RedisLock)")
        public void redisLockAspect(){}
    
        @Around("redisLockAspect()")
        public void lockAroundAction(ProceedingJoinPoint proceeding) throws Exception{
          
    //获取redis锁
    Boolean flag = this.getLock(proceeding, 0, System.currentTimeMillis());
    if (flag) {
    try {
    proceeding.proceed();
    Thread.sleep(PROTECT_TIME);
    } catch (Throwable throwable) {
    throw new RuntimeException("分布式锁执行发生异常" + throwable.getMessage(), throwable);
    } finally {
    // 删除锁
    this.delLock(proceeding);
    }
    } else {
    log.info("其他系统正在执行此项任务");
    }

    } //获取锁 private boolean getLock(ProceedingJoinPoint proceeding,int count,long currentTime){ //获取注解中的参数 Map<String,Object> annotationArgs=this.getAnnotationArgs(proceeding); String lockPrefix=(String)annotationArgs.get(LOCK_PRE_FIX); String key=(String)annotationArgs.get(LOCK_KEY); long expire=(long)annotationArgs.get(TIME_OUT); if (StringUtils.isEmpty(lockPrefix)||StringUtils.isEmpty(key)){ throw new RuntimeException("RedisLock,锁前缀,锁名未设置"); } if(commonRedistHelper.setNx(lockPrefix,key,expire)){ return true; }else{ //如果当前时间与锁的时间差,大于保护时间,则强制删除锁(防止死锁) long createTime=commonRedistHelper.getLockValue(lockPrefix,key); if ((currentTime-createTime)>(expire*1000+PROTECT_TIME)){ count++; if(count>Max_RETRY_COUNT){ return false; } commonRedistHelper.delete(lockPrefix,key); getLock(proceeding,count,currentTime); } return false; } } /** * 删除锁 * */ private void delLock(ProceedingJoinPoint proceeding) { Map<String, Object> annotationArgs=this.getAnnotationArgs(proceeding); String lockPrefix=(String)annotationArgs.get(LOCK_PRE_FIX); String key=(String)annotationArgs.get(LOCK_KEY); commonRedistHelper.delete(lockPrefix,key); } /** * 获取锁参数 * * @param proceeding * @return */ private Map<String, Object> getAnnotationArgs(ProceedingJoinPoint proceeding) { Class target = proceeding.getTarget().getClass(); Method[] methods = target.getMethods(); String methodName = proceeding.getSignature().getName(); for (Method method : methods) { if (method.getName().equals(methodName)) { Map<String, Object> result = new HashMap<String,Object>(); RedisLock redisLock = method.getAnnotation(RedisLock.class); result.put(LOCK_PRE_FIX, redisLock.lockPrefix()); result.put(LOCK_KEY, redisLock.lockKey()); result.put(TIME_OUT, redisLock.timeUnit().toSeconds(redisLock.timeOut())); return result; } } return null; } }

    redis操作

    @Component
    public class CommonRedistHelper {
    
        @Autowired
        RedisTemplate redisTemplate;
        /**
         * 添加分布式锁
         *
         */
        public boolean setNx(String track,String sector,long timeout){
            ValueOperations valueOperations=redisTemplate.opsForValue();
            Boolean flag=valueOperations.setIfAbsent(track+sector,System.currentTimeMillis());
        if (flag){
            valueOperations.set(track+sector,getLockValue(track,sector),timeout, TimeUnit.SECONDS);
        }
        return flag;
        }
        /**
         * 删除锁
         */
        public void delete(String track,String sector){
            redisTemplate.delete(track+sector);
        }
        /**
         * 查询锁
         * @return 写锁时间
         */
        public long getLockValue(String track, String sector) {
            ValueOperations valueOperations = redisTemplate.opsForValue();
            long createTime = (long) valueOperations.get(track + sector);
            return createTime;
        }
    
    
    
    }

    引用注解

        @Scheduled(cron = "${task.cron.tradeData}")
        @RedisLock(lockPrefix = "**",lockKey = "estomysql")
        public void scheduledTask() {}
  • 相关阅读:
    flask 安装及基础学习(url_for反转,静态文件引入)
    collections 模块之Counter
    collections 数据结构模块namedtuple
    docker 私有仓库之Harbor搭建与使用
    ansible Api 2.3-2.4
    Ansible Callback
    saltstack returners
    快速入门Http协议
    小兔JS教程(五) 简单易懂的JSON入门
    小兔JS教程(四)-- 彻底攻略JS数组
  • 原文地址:https://www.cnblogs.com/tsxylhs/p/13558490.html
Copyright © 2011-2022 走看看