基于redis的分布式锁的实现
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
package com.ruoyi.common.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class DistributionLock {
private static final Logger logger = LoggerFactory.getLogger(DistributionLock.class);
private static final String RELEASE_LOCK_TIMES_PRIFFIX = "RELEASE_LOCK_TIMES_";
public static final long DEFAULT_ACQUIRE_TIMEOUT_MS = 1000;
public static final long DEFAULT_LOCK_TIMEOUT_MS = 10000;
private StringRedisTemplate stringRedisTemplate;
private String lockPrefix;
public DistributionLock(StringRedisTemplate stringRedisTemplate, String lockPrefix) {
this.stringRedisTemplate = stringRedisTemplate;
this.lockPrefix = lockPrefix;
}
public String acquireLockWithTimeout(String lockName,
long acquireTimeoutInMS, long lockTimeoutInMS) throws Exception {
logger.info("尝试获取锁,锁名:{}", lockName);
String retIdentifier = null;
String identifier = UUID.randomUUID().toString();
String lockKey = lockPrefix + lockName;
long end = System.currentTimeMillis() + acquireTimeoutInMS;
try {
BoundValueOperations<String, String> boundValueOperations = stringRedisTemplate.boundValueOps(lockKey);
while (System.currentTimeMillis() < end) {
boolean success = boundValueOperations.setIfAbsent(identifier);
if (success) {
boundValueOperations.expire(lockTimeoutInMS, TimeUnit.MILLISECONDS);
retIdentifier = identifier;
return retIdentifier;
}
try {
Thread.sleep(10);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
} catch (Exception e) {
throw new Exception("获取不到redis");
}
return retIdentifier;
}
public boolean releaseLock(String lockName, String identifier) {
logger.info("尝试释放锁,锁名:{}", lockName);
String lockKey = lockPrefix + lockName;
boolean retFlag = true;
try {
BoundValueOperations<String, String> boundValueOperations = stringRedisTemplate.boundValueOps(lockKey);
if (identifier.equals(boundValueOperations.get())) {
stringRedisTemplate.delete(lockKey);
retFlag = true;
}
} catch (Exception e) {
retFlag = false;
}
return retFlag;
}
public void releaseLock(String lockName, String identifier, int times) {
logger.info("尝试释放锁,锁名:{}", lockName);
String lockKey = RELEASE_LOCK_TIMES_PRIFFIX + lockName;
try {
if (stringRedisTemplate.hasKey(lockKey)) {
String timesVal = stringRedisTemplate.opsForValue().get(lockKey);
if (String.valueOf(times).equals(timesVal)) {
return;
}
stringRedisTemplate.boundValueOps(lockKey).increment(1);
} else {
stringRedisTemplate.opsForValue().set(lockKey, "2",60*15,TimeUnit.SECONDS);
}
releaseLock(lockName, identifier);
} catch (Exception e) {
logger.error("获取不到redis");
}
}
}