您的位置:首页 > 数据库 > Redis

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

2017-05-11 16:56 627 查看
思路是:

获取锁使用 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
@Aspect
public 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/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  redis 分布式 aop