基于 AOP 和 Redis 实现的分布式锁

来源:互联网 发布:如何做合格淘宝客服 编辑:程序博客网 时间:2024/06/11 04:12

思路是:

  • 获取锁使用 redis setnx key value 特性 :如果设置成功,返回 1 。 设置失败,返回 0 。
  • 设置key 的过期时间
  • 用完了删除key
  • 采用 AOP 提高开发效率
  • 自定义注解 包含 过期时间,等待时间,key


自定义注解

/** * Created by linving on 2017/4/24. */@Target({ ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface RedisLock {    //等待时间    int maxWait() default 0;    //过期时间    int expiredTime() default 0;    // key    String[] keys() default {};}

AOP实现

/** * Created by linving on 2017/4/21. * TODO * 加鎖 采用注解 */@Component@Aspectpublic class CashLockInterceptor {    public static Logger logger = LoggerFactory.getLogger(CashLockInterceptor.class);    @Autowired     RedisOperator redisOperator;    /**     * 切面 加有 RedisLock 的 service 方法     */    @Pointcut("execution(* com.xx.service..*.*(..)) && @annotation(com.xx.annotation.RedisLock)")    private void cutMethod() {    }    @Before("cutMethod()")    public void doAccessCheck(JoinPoint point) throws NoSuchMethodException {        logger.info("Before...");    }    @AfterReturning("cutMethod()")    public void doAfter(JoinPoint point) {        logger.info("AfterReturning...");    }    @After("cutMethod()")    public void after(JoinPoint point) {        logger.info("After...");    }    @AfterThrowing("cutMethod()")    public void doAfterThrow() {        logger.info("AfterThrowing...");    }    @Around("cutMethod()")    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {        String methodName = pjp.getSignature().getName();        Class<?> classTarget = pjp.getTarget().getClass();        Class<?>[] par = ((MethodSignature) pjp.getSignature()).getParameterTypes();        Method objMethod = classTarget.getMethod(methodName, par);        RedisLock redisLock = objMethod.getDeclaredAnnotation(RedisLock.class);        String[] keys = redisLock.keys();        int maxWait = redisLock.maxWait();        int expiredTime = redisLock.expiredTime();        Object result = null;        try {            logger.info("前置通知");            //获取锁            Arrays.stream(keys).forEach(key -> {                boolean flag = redisOperator.tryGetRedisLock(key, "", maxWait, expiredTime);                if(!flag){              //获取失败抛异常                    throw new APIBusinessException(ErrorCodeEnum.CODE_SYSTEM_GET_MUCH);                }            });            //代理执行            result = pjp.proceed();            logger.info("后置通知");        } catch (Throwable e) {             //释放锁            Arrays.stream(keys).forEach(key->{                redisOperator.releaseLock(key,"");            });            logger.info("异常通知");            throw e;        }        logger.info("返回通知");        //释放锁        Arrays.stream(keys).forEach(key->{            redisOperator.releaseLock(key,"");        });        return result;    }}

更多精彩内容:
http://jblog.top/

0 0
原创粉丝点击