浏览代码

redis分布式锁优化

dengsixing 2 年之前
父节点
当前提交
b895b8f5c1
共有 1 个文件被更改,包括 42 次插入7 次删除
  1. 42 7
      4dkankan-utils-redis/src/main/java/com/fdkankan/redis/util/RedisLockUtil.java

+ 42 - 7
4dkankan-utils-redis/src/main/java/com/fdkankan/redis/util/RedisLockUtil.java

@@ -1,5 +1,6 @@
 package com.fdkankan.redis.util;
 
+import cn.hutool.core.thread.ThreadUtil;
 import cn.hutool.core.util.StrUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -27,17 +28,31 @@ public class RedisLockUtil {
 
     /**
      * 加锁,自旋重试三次
+     * 默认以线程id作为锁的值
      *
      * @param lockKey 锁key
      * @param expireTime 锁过期时间 单位 毫秒
      * @return
      */
     public boolean lock(String lockKey, int expireTime) {
+        return this.lock(lockKey, null, expireTime);
+    }
+
+    /**
+     * 加锁,自旋重试三次
+     * @param lockKey 锁key
+     * @param lockVal 锁value
+     * @param expireTime 锁过期时间 单位 毫秒
+     * @return
+     */
+    public boolean lock(String lockKey, String lockVal, int expireTime) {
         boolean locked = false;
         int tryCount = 3;
-        String threadId = String.valueOf(Thread.currentThread().getId());
+        if(lockVal == null){
+            lockVal = String.valueOf(Thread.currentThread().getId());
+        }
         while (tryCount > 0) {
-            locked = redisTemplate.opsForValue().setIfAbsent(lockKey, threadId, expireTime, TimeUnit.SECONDS);
+            locked = redisTemplate.opsForValue().setIfAbsent(lockKey, lockVal, expireTime, TimeUnit.SECONDS);
             if(locked){
                 return locked;
             }
@@ -45,7 +60,7 @@ public class RedisLockUtil {
             try {
                 Thread.sleep(300);
             } catch (InterruptedException e) {
-                log.error("线程被中断[线程id:" + threadId + "]", e);
+                e.printStackTrace();
             }
         }
         return locked;
@@ -69,21 +84,41 @@ public class RedisLockUtil {
     }
 
     /**
+     * 非原子解锁,可能解别人锁,不安全
+     *
+     * @return
+     */
+    public boolean unlock(String lockKey, String lockVal) {
+        return this.unlock(lockKey, null);
+    }
+
+    /**
      * 使用lua脚本解锁,不会解除别人锁
      *
      * @param
      * @return
      */
     public boolean unlockLua(String lockKey) {
-        String threadId = String.valueOf(Thread.currentThread().getId());
-        if (StrUtil.isEmpty(lockKey) || Objects.isNull(threadId))
+        return this.unlockLua(lockKey, null);
+    }
+
+    /**
+     * 使用lua脚本解锁,不会解除别人锁
+     *
+     * @param
+     * @return
+     */
+    public boolean unlockLua(String lockKey, String lockVal) {
+        if(lockVal == null){
+            lockVal = String.valueOf(Thread.currentThread().getId());
+        }
+        if (StrUtil.isEmpty(lockKey) || Objects.isNull(lockVal))
             return false;
         DefaultRedisScript<Long> redisScript = new DefaultRedisScript();
-//        redisScript.setLocation(new ClassPathResource("unlock.lua"));
         redisScript.setScriptText(UNLOCK_LUA);
         redisScript.setResultType(Long.class);
 
-        Object result = redisTemplate.execute(redisScript, Arrays.asList(lockKey), threadId);
+        Object result = redisTemplate.execute(redisScript, Arrays.asList(lockKey), lockVal);
         return result.equals(Long.valueOf(1));
     }