构建一个锁首先要满足几个条件,

互斥性。同一个锁只能被一个客户端持有。
安全性。永远不会发生死锁。既主动解锁机制。

基于这两点,结合redis的特性,我们将redis的key作为唯一锁。并且设置过期时间。

要获得锁,要用下面这个命令: SET resource_name my_random_value NX PX expireTime

NX:  NOT EXIST,即当key不存在时,我们进行set操作;若key已经存在,则不做任何操作;

PX:设置一个过期时间,具体时间由expireTime 设置

或者EX,PX 后面跟毫秒数,EX,后面跟秒

public class RedisLock {

private String key;
private int expireTimes = 6000;

public RedisLock() {
}

public RedisLock(String key) {
this.key = key;
}

public synchronized boolean lock() {

try {
Jedis jedis = JedisUtil.getJedis();
String result = jedis.set(key, key, “NX”, “PX”, expireTimes);

if (“OK”.equals(result)) {
return false;
}
if (null == result) {
return true;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JedisUtil.close();
}
return false;
}

public synchronized void unlock() {
try {
Jedis jedis = JedisUtil.getJedis();
jedis.del(key);
} catch (Exception e) {
e.printStackTrace();
} finally {
JedisUtil.close();
}
}

}

这个简单的程序,利用redis的过期特性实现简单的锁的功能,当然上面的锁在有些情况下会有问题,比如事务处理时间超长,redis 的key过期了。但是事务还在执行。其他进程尝试加锁成功,事务结束后,unlock的时候,将其他进程的锁给解除了,造成了混乱。

好在我们还有其他的选择,比如redission

https://github.com/redisson/redisson/wiki

redisson是一个非常强大的看客户端,按照他的意思是Redisson – Redis Java client with features of In-Memory Data Grid

什么内存网格化的客户端,用他的lock方法可以实现对redis锁,这里稍微看下,怎么使用:

使用redisson需要引入依赖:

org.redisson
redisson
3.10.4

最长用的用法是

Config config = new Config();
config.useSingleServer().setAddress(“redis://127.0.0.1:6379”);
RedissonClient client =   Redisson.create(config);
RLock rLock =  client.getLock(“abc”);

//加锁
rLock.lock();
//解锁
rLock.unlock();
client.shutdown();

最简单的加锁方法,默认的加锁时间是30秒,如果unlock失败的话,30秒后,key自动过期,

只有当前加锁进程才能进行解锁操作,其他京城解锁会抛出异常

Exception in thread “main” java.lang.IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id: ac128795-f974-4046-9b9c-d60ad0305693 thread-id: 1

这里的lock是可重用锁,多次加锁后,对应的value会增加,需要一一对应去解锁,

如果当前进程加锁用,其他进程也尝试加锁,会阻塞直到当前进程解锁,如果有多个 进程去竞争,会随机分配到一个进程去加锁。

fairlock用法和lock类似,指标不过多个进程竞争锁资源的时候,会按照先后顺序,优先分配给先发起请求的进程。

redisson的锁还有很多种,可以去wiki查看更多用法

https://github.com/redisson/redisson/wiki/8.-%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E5%92%8C%E5%90%8C%E6%AD%A5%E5%99%A8

发表评论

电子邮件地址不会被公开。