RedisSession记一次分布式锁

项目遇到并发,且是分布式项目所以需要用到分布式锁同时使用的是Spring的声明式事物,为了避免直接在代码中加锁导致,锁释放而事物未提交,在并发较大时造成不可预知的错误,采用aop加锁,并设置aop的执行顺序高于声明式事物的形式来实现此功能。

1.添加依赖

项目使用的是springboot2.0,不能使用最新的依赖,会用冲突

compile ('org.redisson:redisson-spring-boot-starter:3.12.5'){
exclude group: "org.redisson", module: "redisson-spring-data-22"
}
compile group: 'org.redisson', name: 'redisson-spring-data-20', version: '3.12.5'

 

2.aop注解

/**
* @author chengang
* @version 1.0
* @date 2020/8/10 13:21
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
@Documented
@Inherited
public @interface RedisLock {
/**
* 锁名
*/
String key();
/**
* 等待时长(ms),默认为0,获取不到锁立即返回。
*
* @return 等待时长 ms
*/
long waitTime() default 2;

/**
* 最大持有锁时间,如果超过该时间仍未主动释放,将自动释放锁。
*
* @return 最大持有锁时间 ms
*/
long leaseTime() default 3;

String msg();
}

3.aop切面

package com.wise.aop;

import com.wise.annotation.RedisLock;
import com.wise.framework.exception.LogicException;
import lombok.extern.slf4j.Slf4j;
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.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;

/**
* @author chengang
* @version 1.0
* @date 2020/8/7 14:41
*/
@Component
@Aspect
@Slf4j
@Order(1)
public class RedisLockAdvice {
@Resource
private Redisson redisson;
private SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-mm-dd hh:mm:ss sss");

@Pointcut(value = "@annotation(redisLock)")
public void pointCut(RedisLock redisLock){
}

@Around(value = "pointCut(redisLock)",argNames = "joinPoint,redisLock")
public Object processAround(ProceedingJoinPoint joinPoint,RedisLock redisLock){
//获取注解的key
String key = redisLock.key();
//根据定义的key获取锁
RLock lock=redisson.getLock(key);
lock.lock();
log.info("========锁{}成功=时间:{}===========",key,convertTimeStr(System.currentTimeMillis()));
// try {
// lock.tryLock(redisLock.waitTime(),redisLock.leaseTime(), TimeUnit.SECONDS);
//
// } catch (InterruptedException e) {
// log.info("==========锁未获取到={}==============",redisLock.msg());
// return null;
// }
Object obj=null;
try{
obj=joinPoint.proceed();
} catch (LogicException e) {
throw e;
} catch (Throwable throwable) {
throwable.printStackTrace();
} finally {
log.info("========锁{}解锁=时间:{}===========",key,convertTimeStr(System.currentTimeMillis()));
lock.unlock();
}
return obj;
}

/**
* 转化时间
* @return
*/
private String convertTimeStr(long time){
return simpleDateFormat.format(time);
}

}

service中的使用

@RedisLock(key="getCutTask",msg = "获取getCutTask锁失败")
@Transactional(rollbackFor = Exception.class)
public void sum(GetCutTask summer) {}

你可能感兴趣的:(RedisSession记一次分布式锁)