2019独角兽企业重金招聘Python工程师标准>>>
Redisson概述
Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service) Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。
Redisson底层采用的是Netty 框架。支持Redis 2.8以上版本,支持Java1.6+以上版本。
Redisson本身封装了很多锁对象,现在redission 基础上做一个分布式锁注解
**一 环境 **
** 1 jdk 1.8 **
** 2 springboot **
** 3 redission **
二 引入依赖
org.springframework.boot
spring-boot-starter
${springboot.version}
org.springframework.boot
spring-boot-starter-web
${springboot.version}
org.redisson
redisson
3.5.5
**三 springboot 整合redission **
** (由于历史遗留原因,此处没有进行参数动态配置,请自行优化)**
private String address="redis://localhost:6379";
private int connectionMinimumIdleSize = 10;
private int idleConnectionTimeout=10000;
private int pingTimeout=1000;
private int connectTimeout=10000;
private int timeout=3000;
private int retryAttempts=3;
private int retryInterval=1500;
private int reconnectionTimeout=3000;
private int failedAttempts=3;
private String password = null;
private int subscriptionsPerConnection=5;
private String clientName=null;
private int subscriptionConnectionMinimumIdleSize = 1;
private int subscriptionConnectionPoolSize = 50;
private int connectionPoolSize = 64;
private int database = 0;
private boolean dnsMonitoring = false;
private int dnsMonitoringInterval = 5000;
private int thread; //当前处理核数量 * 2
private String codec="org.redisson.codec.JsonJacksonCodec";
@Bean(destroyMethod = "shutdown")
RedissonClient redisson() throws Exception {
Config config = new Config();
config.useSingleServer().setAddress(address)
.setConnectionMinimumIdleSize(connectionMinimumIdleSize)
.setConnectionPoolSize(connectionPoolSize)
.setDatabase(database)
.setDnsMonitoring(dnsMonitoring)
.setDnsMonitoringInterval(dnsMonitoringInterval)
.setSubscriptionConnectionMinimumIdleSize(subscriptionConnectionMinimumIdleSize)
.setSubscriptionConnectionPoolSize(subscriptionConnectionPoolSize)
.setSubscriptionsPerConnection(subscriptionsPerConnection)
.setClientName(clientName)
.setFailedAttempts(failedAttempts)
.setRetryAttempts(retryAttempts)
.setRetryInterval(retryInterval)
.setReconnectionTimeout(reconnectionTimeout)
.setTimeout(timeout)
.setConnectTimeout(connectTimeout)
.setIdleConnectionTimeout(idleConnectionTimeout)
.setPingTimeout(pingTimeout)
.setPassword(password);
Codec codec=(Codec)ClassUtils.forName(getCodec(), ClassUtils.getDefaultClassLoader()).newInstance();
config.setCodec(codec);
config.setThreads(thread);
config.setEventLoopGroup(new NioEventLoopGroup());
config.setUseLinuxNativeEpoll(false);
return Redisson.create(config);
}
四 实现分布式锁注解
** 1 定义注解**
/**
* @author: wangjun
* @create: 2018/7/30
*
* 分布式锁
**/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Rlock {
/**
* 分布式锁的key
*/
String localKey();
/**
* 锁释放时间 默认五秒
*
* @return
*/
long leaseTime() default 5*1000;
/**
* 时间格式 默认:毫秒
*
* @return
*/
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
}
** 2 aop配置**
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.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.stereotype.Component;
import com.wj.project.wjcore.annotation.redisLock.Rlock;
/**
* @author: wangjun
* @create: 2018/7/30
**/
@Aspect
@Component
public class RlockAspect {
private final static Logger logger = LoggerFactory.getLogger(RlockAspect.class);
@Autowired
private RedissonClient redissonClient;
@Pointcut("@annotation(com.wj.project.wjcore.annotation.redisLock.Rlock)")
public void RlockAspect() {
}
@Around("RlockAspect()")
public Object arround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object object = null;
RLock lock = null;
logger.info("rlockAspect start ");
try {
Rlock rlockInfo = getRlockInfo(proceedingJoinPoint);
lock = redissonClient.getLock(getLocalKey(proceedingJoinPoint, rlockInfo));
if (lock != null) {
final boolean status = lock.tryLock(rlockInfo.leaseTime(), rlockInfo.timeUnit());
if (status) {
object = proceedingJoinPoint.proceed();
}
}
} finally {
if (lock != null && status == true ) {
lock.unlock();
}
}
return object;
}
public Rlock getRlockInfo(ProceedingJoinPoint proceedingJoinPoint) {
MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
return methodSignature.getMethod().getAnnotation(Rlock.class);
}
/**
* redis lock key 生成逻辑 这里只是简单生成,如需投入生产使用,可考虑复杂化
*
* @param proceedingJoinPoint
* @return
*/
public String getLocalKey(ProceedingJoinPoint proceedingJoinPoint, Rlock rlockInfo) {
StringBuilder localKey = new StringBuilder("Rlock");
final Object[] args = proceedingJoinPoint.getArgs();
MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
String methodName = methodSignature.getMethod().getName();
localKey.append(rlockInfo.localKey()).append(methodName);
return localKey.toString();
}
}
五 使用实践
@Rlock(localKey = "redisLockAnnotation", leaseTime = 3, timeUnit = TimeUnit.MINUTES)
public void redisLockAnnotation() {
try {
logger.info("thread sleep start ");
Thread.sleep(100000);
logger.info("thread sleep end ");
} catch (Exception e) {
e.printStackTrace();
}
}