Bootstrap

基于redisson实现注解版分布式锁

配置

  • 配置文件
singleServerConfig:
  #连接空闲超时,单位:毫秒
  idleConnectionTimeout: 10000
  pingTimeout: 1000
  #连接超时,单位:毫秒
  connectTimeout: 10000
  #命令等待超时,单位:毫秒
  timeout: 3000
  #命令失败重试次数
  retryAttempts: 3
  #命令重试发送时间间隔,单位:毫秒
  retryInterval: 1500
  #重新连接时间间隔,单位:毫秒
  reconnectionTimeout: 3000
  #执行失败最大次数
  failedAttempts: 3
  #单个连接最大订阅数量
  subscriptionsPerConnection: 5
  #客户端名称
  clientName: null
  #地址
  address: "redis://IP:PORT"
  #数据库编号
  database: 0
  #密码
  password: gg123456g
  #发布和订阅连接的最小空闲连接数
  subscriptionConnectionMinimumIdleSize: 1
  #发布和订阅连接池大小
  subscriptionConnectionPoolSize: 50
  #最小空闲连接数
  connectionMinimumIdleSize: 32
  #连接池大小
  connectionPoolSize: 64
  #是否启用DNS监测
  dnsMonitoring: false
  #DNS监测时间间隔,单位:毫秒
  dnsMonitoringInterval: 5000
threads: 0
nettyThreads: 0
codec: !<org.redisson.codec.JsonJacksonCodec> {}
transportMode : "NIO"
  • 配置类
@Configuration
public class RedissionConfig {

    @Bean(destroyMethod = "shutdown")
    RedissonClient redisson() throws Exception {
        RedissonClient redisson = Redisson.create(
                Config.fromYAML(new ClassPathResource("redisson.yml").getInputStream()));
        return redisson;
    }
}

自定义注解

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

    /**
     * 分布式锁的key
     */
    String localKey() default "redisLockAnnotation::";

    /**
     * 等待时间 默认五秒
     *
     * @return
     */
    long waitTime() default 5;

    /**
     * 锁释放时间 默认十秒
     *
     * @return
     */
    long leaseTime() default 10;

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

自定义切面实现

@Aspect
@Component
@Slf4j
public class RlockAspect {

    @Autowired
    private RedissonClient redissonClient;

    @Pointcut("@annotation(com.boss.xtrain.core.db.redis.annotation.Rlock)")
    public void RlockAspect() { }

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

        try {
        	// 获取注解信息
            Rlock rlockInfo = getRlockInfo(proceedingJoinPoint);
            // 根据名字获取锁实例
            lock = redissonClient.getLock(getLocalKey(proceedingJoinPoint, rlockInfo));

            if (lock != null) {
                final boolean status = lock.tryLock(rlockInfo.waitTime(), rlockInfo.leaseTime(), rlockInfo.timeUnit());
                if (status) {
                    object = proceedingJoinPoint.proceed();
                }else{
                    throw new BusinessException(ExceptionMsg.REDISSION_HAS_BEAN_USED, ExceptionMsg.REDISSION_HAS_BEAN_USED_MSG);
                }
            }
        } finally {
            if (lock != null && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return object;
    }

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

    /**
     * @param proceedingJoinPoint
     * @return
     */
    public String getLocalKey(ProceedingJoinPoint proceedingJoinPoint, Rlock rlockInfo) {
        StringBuilder localKey = new StringBuilder();
        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", waitTime = 3, leaseTime = 3, timeUnit = TimeUnit.SECONDS)
public void redisLockAnnotation() {
	try {
		log.info("thread sleep start ");
		Thread.sleep(100000);
		log.info("thread sleep end ");
	} catch (Exception e) {
		e.printStackTrace();
	}
}
;