分布式锁,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() {}

 

posted @ 2020-08-25 11:03  菜鸟的进击  阅读(1822)  评论(0编辑  收藏  举报