您的位置:首页 > 数据库 > Redis

一个纯的java-redis锁,因为有更好的,暂时就只记录一下

2018-01-15 10:15 585 查看
找了很长时间,左试右试的搞了一个redis锁出来,但是被一个更好的方案取代了,有点郁闷,在此记录一下。

开始是因为redis的操作原子性问题,没有用redis自带的key过期,因为setnx 和expire是两个方法,无法保持强一致性,在高并发时候是致命的。而且保留着对redis的自带过期的不信任(这里补充一下,查了资料后发现redis的自带过期还是不错的,两种过期方式,一个是在get的时候判断key是否过期,一个是在空闲时间流出25%cpu时间随机拿带过期的key进行随机淘汰。不过可能在超大的吞吐量的时候可能会因为淘汰不及时,稍微占点内存),就选择了利用value来实现。

@Component
public class NamedLock {

private static final int AUTO_RELEASE_AFTER_MINUTES = 10;
@Autowired
private RedisTemplate redisTemplate;

public boolean tryLock(String name,long useless) {
DateTime now = DateTime.now();
Boolean tryLock = redisTemplate.opsForValue().setIfAbsent(name, now.getMillis());
if (tryLock) {
return true;
} else {
Long lockTime = (Long) redisTemplate.opsForValue().get(name);
if (lockTime == null) {
return redisTemplate.opsForValue().setIfAbsent(name, now.getMillis());
}
if (now.minusMinutes(AUTO_RELEASE_AFTER_MINUTES).isAfter(lockTime)) {
Long originTime = (Long) redisTemplate.opsForValue().getAndSet(name, now.getMillis());
if (originTime == null || originTime.equals(lockTime))
return true;
else
return false;
} else {
return false;
}
}
}

public boolean isLocked(String name) {
return redisTemplate.opsForValue().get(name) == null;
}

public void releaseLock(String name) {
Long lockTime = (Long) redisTemplate.opsForValue().get(name);
if(lockTime != null && DateTime.now().minusMinutes(AUTO_RELEASE_AFTER_MINUTES).isBefore(lockTime)){
redisTemplate.delete(name);
}
return;
}
}

不过后来大神从spring的git里找来一个好方法,就是利用redistemplate的execute,把命令当脚本执行,保证了redis 的setnx和过期的原子性,直接我这个方案就不合适了。还是要多了解api啊。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  redis锁
相关文章推荐