Realization of Redis distributed lock based on SpringBoot AOP aspect-oriented programming

Realization of Redis distributed lock based on SpringBoot AOP aspect-oriented programming Realization of Redis distributed lock based on SpringBoot AOP aspect-oriented programming Realization of Redis distributed lock based on SpringBoot AOP aspect-oriented programming

The goal of locking is to ensure mutual exclusion of the resources it accesses. In practice, this resource is usually a string. Using redis to implement locks is mainly to put resources into redis and take advantage of its atomicity. Some subsequent operations are not allowed if this resource already exists in Redis when accessed by other threads.

Spring Boot uses Redis through RedisTemplate. In actual use, distributed locks can be used at the method level after encapsulation, which is more convenient to use, without the need to acquire and release locks everywhere.

First, define an annotation:

@Target({ElementType.METHOD})  
@Retention(RetentionPolicy.RUNTIME)  
@Inherited  
public [@interface](https://my.oschina.net/u/996807) RedisLock {

     //Locked resource, key for redis
    String value() default "default";

    //lock hold time (in milliseconds) 
    long keepMills() default 30000;

    //Action to take on failure
    LockFailAction action() default LockFailAction.CONTINUE;

    //Action to perform on failure -- enumeration
    public enum LockFailAction{  
        GIVEUP,  
        CONTINUE;  
    }
    //retry interval
    long sleepMills() default 200;
    //number of retries
    int retryTimes() default 5;  
}

Bean with distributed lock

[@Configuration](https://my.oschina.net/pointdance) 
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class DistributedLockAutoConfiguration {    
    @Bean    
    @ConditionalOnBean(RedisTemplate.class)    
    public DistributedLock redisDistributedLock(RedisTemplate redisTemplate){       
        return new RedisDistributedLock(redisTemplate);   
    }
}

Aspect-Oriented Programming - Defining Aspects

@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;  
         //Acquire a distributed lock 
        boolean lock = distributedLock.lock(key, redisLock.keepMills(), retryTimes, redisLock.sleepMills());  
        if(!lock) {  
            logger.debug("get lock failed : " + key);  
            return null;  
        }

       //After executing the method, release the distributed lock
        logger.debug("get lock success : " + key);  
        try {  
            return pjp.proceed();   //execution method
        } catch (Exception e) {  
            logger.error("execute locked method occured an exception", e);  
        } finally {  
            boolean releaseResult = distributedLock.releaseLock(key);  //release distributed lock
            logger.debug("release lock :" + key + (releaseResult ?" success" : "failed"));  
        }  
        return null;  
    }  
}

Instructions

  • When entering this method, a distributed lock is occupied,
  • When the method execution is complete, release the distributed lock
  • Use the same resource, such as multiple functions of your-custom-service-redis-key, to seize the same lock. Whoever grabs it will execute first.
@RedisLock(value="your-custom-service-redis-key")
public void  serviceMethod(){
  //Normal write method implementation
}

Welcome to pay attention to my blog, there are many fine collections in it

  • This article is reproduced to indicate the source (must be linked, not just text): Antetokounmpo Blog .

If you find it helpful, please like and share! Your support is my inexhaustible creative motivation! . In addition, the author has recently output the following fine content, looking forward to your attention.

Tags: Spring Vue.js Redis Spring Boot Spring Cloud jwt Spring Security oauth RBAC around

Posted by p.persia69 on Wed, 01 Jun 2022 05:25:50 +0530