修改多节点同时执行任务情况
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
package com.ruoyi.common.core.redis;
|
package com.ruoyi.common.core.redis;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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.data.redis.core.script.DefaultRedisScript;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -76,10 +78,10 @@ public class DistributedLockUtil {
|
|||||||
* 自定义参数获取锁
|
* 自定义参数获取锁
|
||||||
*/
|
*/
|
||||||
public String acquireLockWithRenewal(String lockKey, long expireSeconds, long acquireTimeoutSeconds) {
|
public String acquireLockWithRenewal(String lockKey, long expireSeconds, long acquireTimeoutSeconds) {
|
||||||
String identifier = UUID.randomUUID().toString();
|
|
||||||
long endTime = System.currentTimeMillis() + acquireTimeoutSeconds * 1000;
|
long endTime = System.currentTimeMillis() + acquireTimeoutSeconds * 1000;
|
||||||
|
|
||||||
while (System.currentTimeMillis() < endTime) {
|
while (System.currentTimeMillis() < endTime) {
|
||||||
|
String identifier = UUID.randomUUID().toString();
|
||||||
boolean locked = tryLockOnce(lockKey, identifier, expireSeconds);
|
boolean locked = tryLockOnce(lockKey, identifier, expireSeconds);
|
||||||
if (locked) {
|
if (locked) {
|
||||||
startRenewal(lockKey, identifier, expireSeconds);
|
startRenewal(lockKey, identifier, expireSeconds);
|
||||||
@@ -116,14 +118,31 @@ public class DistributedLockUtil {
|
|||||||
/**
|
/**
|
||||||
* 尝试获取一次锁
|
* 尝试获取一次锁
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
private boolean tryLockOnce(String lockKey, String identifier, long expireSeconds) {
|
private boolean tryLockOnce(String lockKey, String identifier, long expireSeconds) {
|
||||||
try {
|
try {
|
||||||
if (!redisCache.hasKey(lockKey)) {
|
String lua = "if redis.call('setnx', KEYS[1], ARGV[1]) == 1 then "
|
||||||
redisCache.setCacheObject(lockKey, identifier, (int) expireSeconds, TimeUnit.SECONDS);
|
+ "redis.call('expire', KEYS[1], ARGV[2]) "
|
||||||
String storedId = redisCache.getCacheObject(lockKey);
|
+ "return 1 "
|
||||||
return identifier.equals(storedId);
|
+ "else "
|
||||||
|
+ "return 0 "
|
||||||
|
+ "end";
|
||||||
|
|
||||||
|
// 执行Lua脚本
|
||||||
|
Object result = redisCache.redisTemplate.execute(
|
||||||
|
(RedisCallback<Object>) 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);
|
||||||
}
|
}
|
||||||
return false;
|
);
|
||||||
|
|
||||||
|
boolean success = result != null && Integer.parseInt(result.toString()) == 1;
|
||||||
|
System.out.println("【LUA绝杀锁】节点=" + System.identityHashCode(this)
|
||||||
|
+ " 结果=" + success + " key=" + lockKey);
|
||||||
|
return success;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user