/**
* 加锁(并发不保证原子性)
* @param key
* @param value 当前时间+超时时间
* @return
*/
public boolean lock(String key, String value , StringReidsTemplate redisTemplate) {
if(redisTemplate.opsForValue().setIfAbsent(key, value)) {
return true;
}
String currentValue = redisTemplate.opsForValue().get(key);
//如果锁过期
if (!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()) {
//获取上一个锁的时间
String oldValue = redisTemplate.opsForValue().getAndSet(key, value);
if (!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)) {
return true;
}
}
return false;
}
/**
* 解锁
* @param key
* @param value
*/
public void unlock(String key, String value , StringRedisTemplate redisTemplate) {
try {
String currentValue = redisTemplate.opsForValue().get(key);
if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {
redisTemplate.opsForValue().getOperations().delete(key);
}
}catch (Exception e) {
log.error("【redis分布式锁】解锁异常, {}", e);
}
}
/**
* 加锁(并发保证原子性,并发环境下会耗尽连接池)
* @param key
* @param value
*/
public static boolean lockByTransaction(String lockKey , String value , StringRedisTemplate redis) {
redis.setEnableTransactionSupport(true);
SessionCallback<Boolean> sessionCallback = new SessionCallback<Boolean>() {
List<Object> exec = null;
@Override
@SuppressWarnings("unchecked")
public Boolean execute(RedisOperations operations) throws DataAccessException {
operations.multi();
redis.opsForValue().setIfAbsent(lockKey , value);
redis.expire(lockKey, 5 , TimeUnit.SECONDS);
exec = operations.exec();
if(exec.size() > 0) {
return (Boolean) exec.get(0);
}
return false;
}
};
return redis.execute(sessionCallback);
}
String timestamp = String.valueOf(System.currentTimeMillis() + 5 * 1000L);
lock("redisKey" , timestamp , redisUtil.getStringRedisTemplate());
//正确加锁
public static boolean lockByNX(String lockKey, RedisTemplate redis) { String lock = LOCK_PREFIX + lockKey; return (boolean) redis.execute((RedisCallback<Object>) redisConnection -> { String expireAt = String.valueOf(System.currentTimeMillis() + LOCK_EXPIRE + 1); Boolean nx = redisConnection.setNX(lock.getBytes(), expireAt.getBytes()); if (nx) { return true; } else { byte[] bytes = redisConnection.get(lock.getBytes()); if (Objects.nonNull(bytes) && bytes.length > 0) { long expireTime = Long.parseLong(new String(bytes)); if (expireTime < System.currentTimeMillis()) { byte[] oldValue = redisConnection.getSet(lock.getBytes(), String.valueOf(System.currentTimeMillis() + LOCK_EXPIRE + 1).getBytes()); return Long.parseLong(new String(oldValue)) < System.currentTimeMillis(); } } } return false; }); } public static void unlockByNX(String key, RedisTemplate redis) { redis.delete(key); }