自定义分布式锁注解
Redisson分布式锁自定义注解
import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DistributedLock {
/**
* 锁的名称
*/
String value() default "redisson";
/**
* 锁的有效时间
*/
int expireTime() default 10;
}
分布式锁AOP
import com.it.redis.service.RedissonLockService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* @description: Redisson分布式锁注解AOP
*/
@Slf4j
@Aspect
@Component
public class DistributedLockAspect {
@Autowired(required = false)
RedissonLockService redissonLockService;
@Around("@annotation(distributedLock)")
public void around(ProceedingJoinPoint joinPoint, DistributedLock distributedLock) {
log.info("分布式锁-lock");
//获取锁名称
String lockName = distributedLock.value();
//获取超时时间,默认10秒
int expireTime= distributedLock.expireTime();
boolean isLock = redissonLockService.tryLock(lockName, expireTime);
try {
if (isLock){
log.info("加锁成功,开始执行业务...");
joinPoint.proceed();
log.info("业务执行完成.");
}else {
log.info("尝试获取锁失败, 稍后重试!");
TimeUnit.MILLISECONDS.sleep(200);
}
} catch (Throwable throwable) {
log.error("加锁失败: ", throwable);
throwable.printStackTrace();
} finally {
//如果该线程还持有该锁,那么释放该锁。如果该线程不持有该锁,说明该线程的锁已到过期时间,自动释放锁
if (redissonLockService.isHeldByCurrentThread(lockName)) {
redissonLockService.unlock(lockName);
}
}
log.info("分布式锁-unlock");
}
}
实现方法
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RBucket;
import org.redisson.api.RLock;
import org.redisson.api.RTopic;
import org.redisson.client.codec.StringCodec;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.codec.SerializationCodec;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
/**
* @description: Redisson方法
*/
@Slf4j
@ConditionalOnBean(Redisson.class)
public class RedissonLockService {
@Autowired
private Redisson redisson;
/**
* 加锁操作 (设置锁的有效时间)
*
* @param lockName 锁名称
* @param expireTime 锁有效时间
*/
public void lock(String lockName, long expireTime) {
RLock rLock = redisson.getLock(lockName);
rLock.lock(expireTime, TimeUnit.SECONDS);
}
/**
* 加锁操作 (锁有效时间采用默认时间30秒)
*
* @param lockName 锁名称
*/
public void lock(String lockName) {
RLock rLock = redisson.getLock(lockName);
//默认看门狗3*10s续期,中间完成任务不续期
rLock.lock();
}
/**
* 加锁操作(tryLock锁,没有等待时间)
*
* @param lockName 锁名称
* @param expireTime 锁有效时间
*/
public boolean tryLock(String lockName, long expireTime) {
RLock rLock = redisson.getLock(lockName);
boolean getLock = false;
try {
getLock = rLock.tryLock(expireTime, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error("获取Redisson分布式锁[异常],lockName=" + lockName, e);
e.printStackTrace();
return false;
}
return getLock;
}
/**
* 加锁操作(tryLock锁,有等待时间)
*
* @param lockName 锁名称
* @param leaseTime 锁有效时间
* @param waitTime 等待时间
*/
public boolean tryLock(String lockName, long leaseTime, long waitTime) {
RLock rLock = redisson.getLock(lockName);
boolean getLock = false;
try {
getLock = rLock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error("获取Redisson分布式锁[异常],lockName=" + lockName, e);
e.printStackTrace();
return false;
}
return getLock;
}
/**
* 解锁
*
* @param lockName 锁名称
*/
public void unlock(String lockName) {
redisson.getLock(lockName).unlock();
}
/**
* 判断该锁是否已经被线程持有
*
* @param lockName 锁名称
*/
public boolean isLock(String lockName) {
RLock rLock = redisson.getLock(lockName);
return rLock.isLocked();
}
/**
* 判断该线程是否持有当前锁
*
* @param lockName 锁名称
*/
public boolean isHeldByCurrentThread(String lockName) {
RLock rLock = redisson.getLock(lockName);
return rLock.isHeldByCurrentThread();
}
/**
* 存储缓存
*/
public <T> void setBucket(String key, T value) {
RBucket<T> bucket = redisson.getBucket(key, StringCodec.INSTANCE);
bucket.set(value);
}
/**
* 存储过期缓存
*/
public <T> void setBucket(String key, T value, long expired) {
RBucket<T> bucket = redisson.getBucket(key, JsonJacksonCodec.INSTANCE);
bucket.set(value, expired, TimeUnit.SECONDS);
}
/**
* 读取缓存
*/
public <T> T getBucket(String key, Class<T> clazz) {
RBucket<T> bucket = redisson.getBucket(key, JsonJacksonCodec.INSTANCE);
return bucket.get();
}
/**
* 移除缓存
*/
public void removeBucket(String key) {
redisson.getBucket(key).delete();
}
/**
* 判断缓存是否存在
*/
public boolean existsBucket(String key) {
return redisson.getBucket(key).isExists();
}
/**
* 发布消息
*/
public <T> long publishMessage(String topic, T message) {
//T要实现序列化接口
RTopic rTopic = redisson.getTopic(topic, new SerializationCodec());
long l = rTopic.publish(message);
log.info("message push success.");
return l;
}
/**
* 订阅消息
*/
public <T> void receiveMessage(String topic, Class<T> clazz, BiConsumer<? super CharSequence, T> consumer) {
RTopic rTopic = redisson.getTopic(topic, new SerializationCodec());
rTopic.addListenerAsync(clazz, (charSequence, msg) -> {
//消费的具体内容
consumer.accept(charSequence, msg);
log.info("message consumer complete.");
}
);
}
}