redis分布式锁-基于redisson实现注解

DistributedLock

import java.lang.annotation.*;

/**
 * 用于某些方法加分布式的锁特性 其应用于某个方法 ,如果是高并发的带某个唯一参数的方法,常常在该
 * 方法的关键参数中添加 @Param("KEYSUFFIX"),只能添加一个 庆主要哦;  Param
 * 是 mybatis 的那个参数注解(org.apache.ibatis.annotations.Param)
 *
 *
 */
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface DistributedLock {
    public final String PARAMKEY ="KEYSUFFIX";

    /**
     * 加锁的前缀key 主要用于区分各个业务的方法数据。
     * @return
     */
    String path() default "";

    /**
     * 等待时间-毫秒(tryLock时使用)
     * @return
     */
    long waitTimeOut() default 100  ;

    /**
     * 只有锁时间-以毫秒为单位
     * @return
     */
    long leaseTimeOut() default -1 ;

    /**
     * 是否跟踪(执行时插入一条数据到数据库,并记录执行状态)
     * 对加锁延迟敏感的操作建议设置为false,因为插入数据库,并更新执行状态可能会增加延迟
     */
    boolean trace() default false;
}

DistributedLockHandler

import com.coinsuper.common.constant.ServiceBusinessExceptionCodeEnum;
import com.coinsuper.common.exception.ServiceBusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * 用于某些方法加分布式的同步锁,需要添加注解 DistributedLockTrait
 *
 */
@Component
@Aspect
@Slf4j
public class DistributedLockHandler {
    @Autowired
    private RedissonClient redission;

    /**
     * 获取已经加了注解的方法
     *
     * @param pjp
     * @return
     * @throws Throwable
     */
    @Around(value = "within(*) && @annotation(com.coinsuper.common.lock.support.DistributedLockTrait)")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        Signature signature = pjp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method targetMethod = methodSignature.getMethod();
        DistributedLockTrait redisLockTrait = targetMethod.getDeclaredAnnotation(DistributedLockTrait.class);
        String lockPath = getLockKey(pjp);
        RLock lock = redission.getLock(lockPath);

        boolean locked = false;
        Object result = null;

        try {
            locked = lock.tryLock(redisLockTrait.waitTimeOut(), redisLockTrait.leaseTimeOut(), TimeUnit.MILLISECONDS);
            if (locked) {
                /** * 处理核心业务的逻辑。 */
                result = pjp.proceed();
            } else {
                log.info("DistributedLockTraitHandler: no distributed lock was obtained.");
                throw new ServiceBusinessException(ServiceBusinessExceptionCodeEnum.DISTRIBUTED_LOCK_NOT_GET);
            }
        } catch (InterruptedException ex) {
            log.info(ex.getMessage(), ex);
            throw ex;
        } catch (Exception e) {
            log.info(e.getMessage(), e);
            throw e;
        } finally {
            if (locked) {
                lock.unlock();
            }
        }
        return result;
    }

    /**
     * 获取分布式锁的key
     *
     * @param pjp return
     */
    private String getLockKey(ProceedingJoinPoint pjp) {
        Signature signature = pjp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method targetMethod = methodSignature.getMethod();
        DistributedLockTrait redisLockTrait = targetMethod.getDeclaredAnnotation(DistributedLockTrait.class);
        log.info("redis lock: lockPath = {}, wait = {} ,leaseMs = {}", redisLockTrait.path(), redisLockTrait.waitTimeOut(), redisLockTrait.leaseTimeOut());
        String path = StringUtils.isBlank(redisLockTrait.path()) ? (targetMethod.getDeclaringClass().getSimpleName() + "::" + methodSignature.getMethod().getName()) : redisLockTrait.path();
        String suffix = "";
        Object[] parameters = pjp.getArgs();
        /**
         * 获取锁的后缀值
         */
        for (Object parameter : parameters) {
            if (null == parameter) {
                continue;
            }
            if (null != parameter.getClass().getAnnotationsByType(Param.class)) {
                /** 一个方法多个参数 获取只有注解 'KEYSUFFIX 的参数*/
                Annotation[][] annotations = targetMethod.getParameterAnnotations();
                for (Annotation[] annotationi : annotations) {
                    /** 一个参数多个注解 'KEYSUFFIX 的参数 */
                    for (Annotation annotation : annotationi) {
                        if (annotation instanceof Param && ((Param) annotation).value().equals(DistributedLockTrait.PARAMKEY)) {
                            suffix = "_" + parameter.toString();
                            break;
                        }
                    }
                }
            }
        }
        String lockPath = path + suffix;
        return lockPath;
    }
}

使用

@DistributedLock
public void test() {
   
}

转载于:https://my.oschina.net/u/3293247/blog/1934422

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值