<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.13.1</version>
</dependency>
spring.redis.cluster.nodes格式为IP:PORT,IP:PORT,IP:PORT,IP:PORT
@Value("${spring.redis.cluster.nodes}")
private String redisCluster;
@Bean
public RedissonClient redisson(){
Config config = new Config();
ClusterServersConfig serversConfig = config.useClusterServers();
List<String> nodeAddresses = Arrays.asList(redisCluster.split(","));
int size = nodeAddresses.size();
String[] address = new String[size];
for(int i=0;i<size;i++){
address[i] = "redis://"+nodeAddresses.get(i);
}
serversConfig.addNodeAddress(address).setScanInterval(5000);
return Redisson.create(config);
}
- 注解类,使用注解实现分布式锁功能,lockKey为锁的key值
package *.redis;
import java.lang.annotation.*;
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedissonLock {
String lockKey() default "";
}
- 切入注解RedissonLock,可在注解的方法上加上分布式锁
package *.redis;
import com.google.common.base.Strings;
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.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
@Component
@Scope
@Aspect
@Order(1)
public class RedisLockAspect {
@Autowired
private RedissonClient redissonClient;
private Logger logger = LoggerFactory.getLogger(RedisLockAspect.class);
@Pointcut("@annotation(*.RedissonLock)")
public void lockAspect() {
}
@Around("lockAspect()")
public Object around(ProceedingJoinPoint joinPoint) {
boolean isLock = false;
Object obj = null;
String lockKey = "";
Signature signature = joinPoint.getSignature();
MethodSignature msg=(MethodSignature) signature;
Object target = joinPoint.getTarget();
//获取注解标注的方法
try {
Method method = target.getClass().getMethod(msg.getName(), msg.getParameterTypes());
//通过方法获取注解
RedissonLock annotation = method.getAnnotation(RedissonLock.class);
lockKey = annotation.lockKey();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
if (!Strings.isNullOrEmpty(lockKey)){
RLock lock = redissonClient.getLock(lockKey);
try {
//第一个参数:获取锁的最长时间
//第二个参数:设置锁的过期时间, 形象的解释就是, 如果超过leaseTime还没有解锁的话, 我就强制解锁.
isLock = lock.tryLock(5,60, TimeUnit.SECONDS);
if(isLock){//如果已成功获取锁
obj = joinPoint.proceed();
}else {
logger.warn("Lock not acquired successfully ");
}
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException();
} finally{
if(isLock){//释放锁
lock.unlock();
}
}
}else {
logger.error("Annotation need a parameter called 'lockKey'");
}
return obj;
}
}
- 最后在需要上锁的功能上加上注解@RedissonLock即可 ,在注解的方法获取锁超过5秒后,就不会在执行注解的方法了