加锁代码如下:
/**
* @param key 要加锁的key
* @param expireAt millis 加锁时间戳
* @return 加锁成功返回true
*/
public boolean lock(String key, long expireAt) {
long now = ensure(expireAt);
Boolean open = redisTemplate.opsForValue().setIfAbsent(key, expireAt);
if (open) {
redisTemplate.expire(key, expireAt - now, TimeUnit.MILLISECONDS);
} else {
Long oldTtl = redisTemplate.opsForValue().get(key);
if (null == oldTtl || oldTtl < now) {
Long preTtl = redisTemplate.opsForValue().getAndSet(key, expireAt);
if (null == preTtl || preTtl.equals(oldTtl)) {
return true;
}
}
}
return open == null ? false : open;
}
/**
* 解锁
*
* @param key key
* @param expireAt millis ,时间戳,只有与加锁时指定的相同时才生效
*/
public void unlock(String key, long expireAt) {
Long ttl = redisTemplate.opsForValue().get(key);
if (null == ttl || expireAt == ttl) {
redisTemplate.delete(key);
}
}
private long ensure(long expireAt) {
long now = System.currentTimeMillis();
if (now >= expireAt) throw new IllegalArgumentException("'expireAt' must be positive");
return now;
}
}
使用时如:
Long expireAt = System.currentTimeMillis() + 10 * 60 * 1000; // 加锁10分钟
if (redisLock.lock(RedisConstraint.sendDataSyncLockKey("some_key", expireAt)) {
....
redisLock.unlock(RedisConstraint.sendDataSyncLockKey("some_key", expireAt);
}