基於SpringBoot AOP面向切面編程實現Redis分布式鎖


基於SpringBoot AOP面向切面編程實現Redis分布式鎖
基於SpringBoot AOP面向切面編程實現Redis分布式鎖
基於SpringBoot AOP面向切面編程實現Redis分布式鎖

鎖定的目標是確保相互排斥其訪問的資源。實際上,此資源通常是字符串。使用redis實現鎖主要是將資源放入redis中並利用其原子性。當其他線程訪問時,如果Redis中已經存在此資源,則不允許進行某些后續操作。

Spring Boot通過RedisTemplate使用Redis,在實際使用過程中,分布式鎖可以在封裝后在方法級別使用,這樣使用起來就更方便了,無需到處獲取和釋放鎖。

首先,定義一個注解:

@Target({ElementType.METHOD})  
@Retention(RetentionPolicy.RUNTIME)  
@Inherited  
public @interface RedisLock {

     //鎖定的資源,redis的鍵
    String value() default "default";

    //鎖定保持時間(以毫秒為單位) 
    long keepMills() default 30000;

    //失敗時執行的操作
    LockFailAction action() default LockFailAction.CONTINUE;

    //失敗時執行的操作--枚舉
    public enum LockFailAction{  
        GIVEUP,  
        CONTINUE;  
    }
    //重試的間隔
    long sleepMills() default 200;
    //重試次數
    int retryTimes() default 5;  
}

具有分布式鎖的Bean

@Configuration 
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class DistributedLockAutoConfiguration {    
    @Bean    
    @ConditionalOnBean(RedisTemplate.class)    
    public DistributedLock redisDistributedLock(RedisTemplate redisTemplate){       
        return new RedisDistributedLock(redisTemplate);   
    }
}

面向切面編程-定義切面

@Aspect  
@Configuration  
@ConditionalOnClass(DistributedLock.class)  
@AutoConfigureAfter(DistributedLockAutoConfiguration.class)  
public class DistributedLockAspectConfiguration {

    private final Logger logger = LoggerFactory.getLogger(DistributedLockAspectConfiguration.class);

    @Autowired  
    private DistributedLock distributedLock;

    @Pointcut("@annotation(com.itopener.lock.redis.spring.boot.autoconfigure.annotations.RedisLock)")  
    private void lockPoint(){

    }

    @Around("lockPoint()")  
    public Object around(ProceedingJoinPoint pjp) throws Throwable{  
        Method method = ((MethodSignature) pjp.getSignature()).getMethod();  
        RedisLock redisLock = method.getAnnotation(RedisLock.class);  
        String key = redisLock.value();  
        if(StringUtils.isEmpty(key)){  
            Object\[\] args = pjp.getArgs();  
            key = Arrays.toString(args);  
        }  
        int retryTimes = redisLock.action().equals(LockFailAction.CONTINUE) ? redisLock.retryTimes() : 0;  
         //獲取分布式鎖 
        boolean lock = distributedLock.lock(key, redisLock.keepMills(), retryTimes, redisLock.sleepMills());  
        if(!lock) {  
            logger.debug("get lock failed : " + key);  
            return null;  
        }

       //執行方法之后,釋放分布式鎖
        logger.debug("get lock success : " + key);  
        try {  
            return pjp.proceed();   //執行方法
        } catch (Exception e) {  
            logger.error("execute locked method occured an exception", e);  
        } finally {  
            boolean releaseResult = distributedLock.releaseLock(key);  //釋放分布式鎖
            logger.debug("release lock :" + key + (releaseResult ?" success" : "failed"));  
        }  
        return null;  
    }  
}

使用方法

  • 進入該方法時,占用分布式鎖,
  • 方法執行完成時,釋放分布式鎖
  • 使用同一個資源,如your-custom-service-redis-key的多個函數,搶占同一個鎖。誰搶到誰先執行。
@RedisLock(value="your-custom-service-redis-key")
public void  serviceMethod(){
  //正常寫方法實現
}

歡迎關注我的博客,里面有很多精品合集

  • 本文轉載注明出處(必須帶連接,不能只轉文字):字母哥博客

覺得對您有幫助的話,幫我點贊、分享!您的支持是我不竭的創作動力! 。另外,筆者最近一段時間輸出了如下的精品內容,期待您的關注。


免責聲明!

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



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