From 10a28b1b0bbc2dc64d5e745353ca3a137c31e5c1 Mon Sep 17 00:00:00 2001 From: sh Date: Thu, 2 Apr 2026 17:15:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=A4=9A=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E5=90=8C=E6=97=B6=E6=89=A7=E8=A1=8C=E4=BB=BB=E5=8A=A1=E6=83=85?= =?UTF-8?q?=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/redis/DistributedLockUtil.java | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/DistributedLockUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/DistributedLockUtil.java index a4c8200..a7b87da 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/DistributedLockUtil.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/DistributedLockUtil.java @@ -1,6 +1,8 @@ package com.ruoyi.common.core.redis; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.connection.ReturnType; +import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.stereotype.Component; @@ -76,10 +78,10 @@ public class DistributedLockUtil { * 自定义参数获取锁 */ public String acquireLockWithRenewal(String lockKey, long expireSeconds, long acquireTimeoutSeconds) { - String identifier = UUID.randomUUID().toString(); long endTime = System.currentTimeMillis() + acquireTimeoutSeconds * 1000; while (System.currentTimeMillis() < endTime) { + String identifier = UUID.randomUUID().toString(); boolean locked = tryLockOnce(lockKey, identifier, expireSeconds); if (locked) { startRenewal(lockKey, identifier, expireSeconds); @@ -116,14 +118,31 @@ public class DistributedLockUtil { /** * 尝试获取一次锁 */ + @SuppressWarnings("unchecked") private boolean tryLockOnce(String lockKey, String identifier, long expireSeconds) { try { - if (!redisCache.hasKey(lockKey)) { - redisCache.setCacheObject(lockKey, identifier, (int) expireSeconds, TimeUnit.SECONDS); - String storedId = redisCache.getCacheObject(lockKey); - return identifier.equals(storedId); - } - return false; + String lua = "if redis.call('setnx', KEYS[1], ARGV[1]) == 1 then " + + "redis.call('expire', KEYS[1], ARGV[2]) " + + "return 1 " + + "else " + + "return 0 " + + "end"; + + // 执行Lua脚本 + Object result = redisCache.redisTemplate.execute( + (RedisCallback) connection -> { + byte[] script = lua.getBytes(); + byte[] key = redisCache.redisTemplate.getStringSerializer().serialize(lockKey); + byte[] val = redisCache.redisTemplate.getStringSerializer().serialize(identifier); + byte[] exp = String.valueOf(expireSeconds).getBytes(); + return connection.eval(script, ReturnType.INTEGER, 1, key, val, exp); + } + ); + + boolean success = result != null && Integer.parseInt(result.toString()) == 1; + System.out.println("【LUA绝杀锁】节点=" + System.identityHashCode(this) + + " 结果=" + success + " key=" + lockKey); + return success; } catch (Exception e) { return false; }