利用redission实现分布式锁(注解实现)

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

Redisson概述

Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service) Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。

Redisson底层采用的是Netty 框架。支持Redis 2.8以上版本,支持Java1.6+以上版本。

Redisson本身封装了很多锁对象,现在redission 基础上做一个分布式锁注解

**一 环境 **

**    1 jdk 1.8 **

**    2 springboot **

**    3 redission **

二 引入依赖

  
    
      org.springframework.boot
      spring-boot-starter
      ${springboot.version}
    

    
    
      org.springframework.boot
      spring-boot-starter-web
      ${springboot.version}
    

    
      org.redisson
      redisson
      3.5.5
    

**三 springboot 整合redission **

** (由于历史遗留原因,此处没有进行参数动态配置,请自行优化)**

    private String address="redis://localhost:6379";
    private int connectionMinimumIdleSize = 10;
    private int idleConnectionTimeout=10000;
    private int pingTimeout=1000;
    private int connectTimeout=10000;
    private int timeout=3000;
    private int retryAttempts=3;
    private int retryInterval=1500;
    private int reconnectionTimeout=3000;
    private int failedAttempts=3;
    private String password = null;
    private int subscriptionsPerConnection=5;
    private String clientName=null;
    private int subscriptionConnectionMinimumIdleSize = 1;
    private int subscriptionConnectionPoolSize = 50;
    private int connectionPoolSize = 64;
    private int database = 0;
    private boolean dnsMonitoring = false;
    private int dnsMonitoringInterval = 5000;

    private int thread; //当前处理核数量 * 2

    private String codec="org.redisson.codec.JsonJacksonCodec";

    @Bean(destroyMethod = "shutdown")
    RedissonClient redisson() throws Exception {
        Config config = new Config();
        config.useSingleServer().setAddress(address)
                .setConnectionMinimumIdleSize(connectionMinimumIdleSize)
                .setConnectionPoolSize(connectionPoolSize)
                .setDatabase(database)
                .setDnsMonitoring(dnsMonitoring)
                .setDnsMonitoringInterval(dnsMonitoringInterval)
                .setSubscriptionConnectionMinimumIdleSize(subscriptionConnectionMinimumIdleSize)
                .setSubscriptionConnectionPoolSize(subscriptionConnectionPoolSize)
                .setSubscriptionsPerConnection(subscriptionsPerConnection)
                .setClientName(clientName)
                .setFailedAttempts(failedAttempts)
                .setRetryAttempts(retryAttempts)
                .setRetryInterval(retryInterval)
                .setReconnectionTimeout(reconnectionTimeout)
                .setTimeout(timeout)
                .setConnectTimeout(connectTimeout)
                .setIdleConnectionTimeout(idleConnectionTimeout)
                .setPingTimeout(pingTimeout)
                .setPassword(password);
        Codec codec=(Codec)ClassUtils.forName(getCodec(), ClassUtils.getDefaultClassLoader()).newInstance();
        config.setCodec(codec);
        config.setThreads(thread);
        config.setEventLoopGroup(new NioEventLoopGroup());
        config.setUseLinuxNativeEpoll(false);
        return Redisson.create(config);
    }

四 实现分布式锁注解

**   1 定义注解**

/**
 * @author: wangjun
 * @create: 2018/7/30
 *
 * 分布式锁
 **/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Rlock {

  /**
   * 分布式锁的key
   */
  String localKey();

  /**
   * 锁释放时间 默认五秒
   *
   * @return
   */
  long leaseTime() default 5*1000;

  /**
   * 时间格式 默认:毫秒
   *
   * @return
   */
  TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
}

**     2 aop配置**


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.aspectj.lang.reflect.MethodSignature;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.wj.project.wjcore.annotation.redisLock.Rlock;


/**
 * @author: wangjun
 * @create: 2018/7/30
 **/
@Aspect
@Component
public class RlockAspect {

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

  @Autowired
  private RedissonClient redissonClient;

  @Pointcut("@annotation(com.wj.project.wjcore.annotation.redisLock.Rlock)")
  public void RlockAspect() {
  }

  @Around("RlockAspect()")
  public Object arround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    Object object = null;
    RLock lock = null;

    logger.info("rlockAspect start ");

    try {
      Rlock rlockInfo = getRlockInfo(proceedingJoinPoint);
      lock = redissonClient.getLock(getLocalKey(proceedingJoinPoint, rlockInfo));

      if (lock != null) {
        final boolean status = lock.tryLock(rlockInfo.leaseTime(), rlockInfo.timeUnit());
        if (status) {
          object = proceedingJoinPoint.proceed();
        }
      }
    } finally {
      if (lock != null && status == true ) {
        lock.unlock();
      }
    }
    return object;
  }

  public Rlock getRlockInfo(ProceedingJoinPoint proceedingJoinPoint) {
    MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
    return methodSignature.getMethod().getAnnotation(Rlock.class);
  }

  /**
   * redis lock key 生成逻辑  这里只是简单生成,如需投入生产使用,可考虑复杂化
   *
   * @param proceedingJoinPoint
   * @return
   */
  public String getLocalKey(ProceedingJoinPoint proceedingJoinPoint, Rlock rlockInfo) {
    StringBuilder localKey = new StringBuilder("Rlock");
    final Object[] args = proceedingJoinPoint.getArgs();

    MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
    String methodName = methodSignature.getMethod().getName();
    localKey.append(rlockInfo.localKey()).append(methodName);

    return localKey.toString();
  }
}

五 使用实践

 @Rlock(localKey = "redisLockAnnotation", leaseTime = 3, timeUnit = TimeUnit.MINUTES)
  public void redisLockAnnotation() {
    try {
      logger.info("thread sleep start ");
      Thread.sleep(100000);
      logger.info("thread sleep end ");
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

转载于:https://my.oschina.net/wangjunBlog/blog/1919734

你可能感兴趣的:(利用redission实现分布式锁(注解实现))