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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM