|
@@ -0,0 +1,122 @@
|
|
|
+package com.txz.mall.util;
|
|
|
+
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+
|
|
|
+import org.redisson.api.RLock;
|
|
|
+import org.redisson.api.RedissonClient;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+
|
|
|
+import javax.annotation.PostConstruct;
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+@Slf4j
|
|
|
+@Component
|
|
|
+public class RedissonLockUtil {
|
|
|
+
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private RedissonClient redissonClient;
|
|
|
+
|
|
|
+ private static RedissonLockUtil instance;
|
|
|
+
|
|
|
+
|
|
|
+ private RedissonLockUtil() {}
|
|
|
+
|
|
|
+
|
|
|
+ @PostConstruct
|
|
|
+ public void init() {
|
|
|
+ instance = this;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 获取分布式锁(阻塞式,直到获取锁为止)
|
|
|
+ * @param lockKey 锁的唯一标识
|
|
|
+ * @return 锁对象
|
|
|
+ */
|
|
|
+ public static RLock getLock(String lockKey) {
|
|
|
+ RLock lock = instance.redissonClient.getLock(lockKey);
|
|
|
+ try {
|
|
|
+ // 尝试获取锁,一直阻塞直到获取成功
|
|
|
+ lock.lock();
|
|
|
+ log.info("获取锁成功,lockKey: {}", lockKey);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取锁失败,lockKey: {}, 异常: {}", lockKey, e.getMessage());
|
|
|
+ throw new RuntimeException("获取分布式锁失败", e);
|
|
|
+ }
|
|
|
+ return lock;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取分布式锁(带超时,超过时间未获取则放弃)
|
|
|
+ * @param lockKey 锁的唯一标识
|
|
|
+ * @param waitTime 等待获取锁的最大时间(单位:秒)
|
|
|
+ * @param leaseTime 锁的自动释放时间(单位:秒)
|
|
|
+ * @return 是否获取到锁
|
|
|
+ */
|
|
|
+ public static boolean tryLock(String lockKey, int waitTime, int leaseTime) {
|
|
|
+ RLock lock = instance.redissonClient.getLock(lockKey);
|
|
|
+ try {
|
|
|
+ // 尝试在 waitTime 秒内获取锁,若获取成功则保持 leaseTime 秒后自动释放
|
|
|
+ boolean isLocked = lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
|
|
|
+ if (isLocked) {
|
|
|
+ log.info("尝试获取锁成功,lockKey: {}", lockKey);
|
|
|
+ } else {
|
|
|
+ log.warn("尝试获取锁失败,lockKey: {}", lockKey);
|
|
|
+ }
|
|
|
+ return isLocked;
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ log.error("尝试获取锁被中断,lockKey: {}, 异常: {}", lockKey, e.getMessage());
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ return false;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("尝试获取锁异常,lockKey: {}, 异常: {}", lockKey, e.getMessage());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 释放分布式锁
|
|
|
+ * @param lockKey 锁的唯一标识
|
|
|
+ */
|
|
|
+ public static void unlock(String lockKey) {
|
|
|
+ RLock lock = instance.redissonClient.getLock(lockKey);
|
|
|
+ try {
|
|
|
+ if (lock.isLocked() && lock.isHeldByCurrentThread()) {
|
|
|
+ lock.unlock();
|
|
|
+ log.info("释放锁成功,lockKey: {}", lockKey);
|
|
|
+ } else {
|
|
|
+ log.warn("释放锁失败,锁未被当前线程持有或已释放,lockKey: {}", lockKey);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("释放锁异常,lockKey: {}, 异常: {}", lockKey, e.getMessage());
|
|
|
+ throw new RuntimeException("释放分布式锁失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 释放分布式锁(带锁对象,用于 tryLock 场景)
|
|
|
+ * @param lock 锁对象
|
|
|
+ */
|
|
|
+ public static void unlock(RLock lock) {
|
|
|
+ try {
|
|
|
+ if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {
|
|
|
+ lock.unlock();
|
|
|
+ log.info("释放锁成功,lockKey: {}", lock.getName());
|
|
|
+ } else {
|
|
|
+ log.warn("释放锁失败,锁未被当前线程持有或已释放,lockKey: {}", lock.getName());
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("释放锁异常,lockKey: {}, 异常: {}", lock.getName(), e.getMessage());
|
|
|
+ throw new RuntimeException("释放分布式锁失败", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 关闭 Redisson 客户端(项目关闭时调用)
|
|
|
+ public static void shutdown() {
|
|
|
+ if (instance.redissonClient != null) {
|
|
|
+ instance.redissonClient.shutdown();
|
|
|
+ log.info("Redisson 客户端已关闭");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|