承接国内外服务器租用托管、定制开发、网站代运营、网站seo优化托管接单、网站代更新,新老站点皆可!!咨询QQ:3787320601

锁Redis Java实现锁机制及过期处理

管理员 2023-06-12 08:38:33 互联网圈 30 ℃ 0 评论 4525字 收藏

锁Redis Java实现锁机制及过期处理

Redis作为一种高性能的key-value数据库,被广泛利用在散布式系统中,Redis的原子性及高性能特点容易被散布式系统用于实现散布式锁,以避免同享数据的修改。

Redis实现锁机制可以使用setNx+expire命令来实现,setNx命令可以在当前实例判断key会不会还未被取得,如果key不存在,表示当前实例取得了该key的控制权,此时就能够使用expire命令设置该key的有效期.这样客户端在取得key的控制权以后,就能够让key在一定时间内保持有效,从而保证数据没有多个客户端同时修改的风险。

在Java中,使用Redis实现散布式锁,可以利用RedisTemplate来操作Redis,以JUC为基础,可通过实现一个locker接口来实现一个基于Redis实现散布式锁的locker类,以下所示:

public interface Locker {

boolean lock(String key);

boolean unlock(String key);
}

public class RedisLocker implements Locker {
private RedisTemplate redisTemplate;
private static final int DEFAULT_ACQUIRY_RESOLUTION_MILLIS = 100;

/**
* 锁超时时间,避免线程在入锁以后,无穷的履行等待
*/
private int expireMsecs = 60 * 1000;
/**
* 锁等待时间,避免线程饥饿
*/
private int timeoutMsecs = 10 * 1000;
private boolean locked = false;

public RedisLocker(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Override
public synchronized boolean lock(String key) {
int timeout = timeoutMsecs;
while (timeout >= 0) {
long expires = System.currentTimeMillis() + expireMsecs + 1;
String expiresStr = String.valueOf(expires); //锁到期时间
if (this.redisTemplate.opsForValue().setIfAbsent(key, expiresStr)) {
locked = true;
return true;
}
String currentValueStr = (String) redisTemplate.opsForValue().get(key); //redis里的时间
if (currentValueStr != null && Long.parseLong(currentValueStr)
//判断会不会为空,不为空的情况下,如果被其他线程设置了值,则第二个条件判断是过不去的
String oldValueStr = this.redisTemplate.opsForValue().getAndSet(key, expiresStr);
//获得上一个锁到期时间,并设置现在的锁到期时间,
//只有一个线程才能获得上一个线上的设置时间,由于jedis.getSet是同步的
if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {
//避免误删(覆盖,由于key是相同的)了他人的锁——这里达不到效果,这里值会被覆盖,但是由于甚么相差了很少的时间,所以可以接受
locked = true;
return true;
}
}
timeout -= DEFAULT_ACQUIRY_RESOLUTION_MILLIS;
/*
延迟100毫秒, 这里使用随机时间可能会好一点,可以避免饥饿进程的出现,即,当同时到达多个进程,
只会有一个进程取得锁,其他的都用一样的频率进行尝试,后面有来了一些进行,也以一样的频率申请锁,
这将可能致使前面来的锁得不到满足.使用随机的等待时间可以一定程度上保证公平性
*/
try {
Thread.sleep(DEFAULT_ACQUIRY_RESOLUTION_MILLIS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return false;
}
@Override
public synchronized boolean unlock(String key) {
if (locked) {
redisTemplate.delete(key);
locked = false;
return true;
}
return false;
}
}

以上实现了基于Redis实现的散布式锁,不过由于其是基于时间的实现,也就意味着,如果锁的具有者在有效期到期之前没有完成持有锁的任务,或由于宕机等缘由Decression时锁未能被删除,则锁会在有效期内永久失效,这是实际开发利用中需要注意处理的

文章来源:丸子建站

文章标题:锁Redis Java实现锁机制及过期处理

https://www.wanzijz.com/view/52722.html

X

截屏,微信识别二维码

微信号:weimawl

(点击微信号复制,添加好友)

打开微信