请老师帮忙看看,在RedisShardedPoolUtil.java 中这样实现有没有问题?谢谢~~
/**
* 带过期时间的分布式锁
*
* @param key
* @param seconds 有效期时间(秒)
* @return
*/
public static Long setnxEx(String key, int seconds) {
try {
try (ShardedJedis jedis = RedisShardedPool.getJedis()) {
// 尝试获取锁
Long setnxResult = jedis.setnx(key, String.valueOf(System.currentTimeMillis() + seconds * 1000));
if (setnxResult == null || setnxResult.intValue() != 1) {
// 未获取到锁,继续判断时间戳,看是否可以重置并获取到锁
String lockValueStr = jedis.get(key);
if (lockValueStr != null && System.currentTimeMillis() < Long.parseLong(lockValueStr)) {
// key存在且时间戳未过,获取锁失败
return 0L;
}
// key不存在(已经过期或被删除)或者时间戳已过,利用getset原子操作尝试获取
String getsetResult = jedis.getSet(key, String.valueOf(System.currentTimeMillis() + seconds * 1000));
if (getsetResult != null && !StringUtils.equals(lockValueStr, getsetResult)) {
// key已经被其他请求重置并获取锁,本次请求获取锁失败(负面后果:少量延长了该锁的时间戳)
return 0L;
}
// key不存在(已经过期或被删除)或者key的原值与前面获取的相同(表示没有其他请求重置key并获取到锁),获取锁成功
setnxResult = 1L;
}
// 获取锁成功,设置超时
Long expireResult = jedis.expire(key, seconds);
if (expireResult == null || expireResult.intValue() != 1) {
throw new Exception("set key: " + key + " expire error. return: " + expireResult);
}
return setnxResult;
}
} catch (Exception e) {
log.error("setnxEx key: {} error", key, e);
}
return null;
}