基于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(){  //正常写方法实现}

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

  • 本文转载注明出处(必须带连接,不能只转文字):字母哥博客。

觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力! 。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。

  • 《手摸手教你学Spring Boot2.0》
  • 《Spring Security-JWT-OAuth2一本通》
  • 《实战前后端分离RBAC权限管理系统》
  • 《实战SpringCloud微服务从青铜到王者》
  • 《VUE深入浅出系列》