zl程序教程

您现在的位置是:首页 >  后端

当前栏目

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

JAVARedis 实现 处理 过期 机制 RedisJava
2023-06-13 09:14:35 时间

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时锁未能被删除,则锁会在有效期内永久失效,这是实际开发应用中需要注意处理的


我想要获取技术服务或软件
服务范围:MySQL、ORACLE、SQLSERVER、MongoDB、PostgreSQL 、程序问题
服务方式:远程服务、电话支持、现场服务,沟通指定方式服务
技术标签:数据恢复、安装配置、数据迁移、集群容灾、异常处理、其它问题

本站部分文章参考或来源于网络,如有侵权请联系站长。
数据库远程运维 锁Redis Java实现锁机制及过期处理(redisjava过期)