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

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

基于这两点,结合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,这个项目提供了一个叫watchdog(看门狗)的概念,大致意思就是watchdog默认30秒会去检查下,是否需要继续续租。俗称看门狗续命

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

120 对 “用redis构建一个分布式锁”的想法;

  1. I have been browsing online more than 2 hours
    today, yet I never found any interesting article like yours.
    It’s pretty worth enough for me. In my opinion, if all webmasters and
    bloggers made good content as you did, the net will
    be much more useful than ever before.

  2. Woah! I’m really digging the template/theme of this blog.
    It’s simple, yet effective. A lot of times it’s challenging to get that “perfect balance” between superb usability and appearance.
    I must say you have done a very good job with this.
    Also, the blog loads super quick for me on Safari.
    Superb Blog!

  3. I’ve been surfing on-line more than 3 hours as of
    late, but I by no means found any interesting article like yours.
    It is beautiful worth sufficient for me. In my view,
    if all website owners and bloggers made just right content as you did, the web will probably be a
    lot more useful than ever before.

  4. Its such as you learn my thoughts! You seem to grasp a lot about this, like you wrote the ebook in it or
    something. I feel that you can do with some % to
    power the message home a little bit, however instead of that, this is great blog.
    A great read. I will definitely be back.

发表评论