分布式锁中的基于redis的setnx的原理以及set和setnx的区别...

  • 时间:
  • 浏览:0
  • 来源:跟我学网络

基于Redis实现分布式锁。虽然网上介绍的Redis分布式锁博客比较多,却有着各种各样的问题,本篇博客将详细介绍如何正确地使用setnx实现Redis分布式锁

这里就不介绍错误的示范了 大家直接看正确的例子:

//保存客户端标识

private static final ThreadLocal<String> LOCAL = new ThreadLocal<String>();

/**

*

* @param jedis

* @param lockKey 锁key

* @param expires 过期时间 一般为 System.currentTimeMillis()+ 过期时间

* @return

*/

public static boolean getDistributedLock(Jedis jedis, String lockKey, long expires) {

//客户端标识 在释放锁时 确保由设置锁的客户端来释放自己的锁

String uuid = UUID.randomUUID().toString();

LOCAL.set(uuid);

String expiresStr = uuid+"#"+expires;

// 如果当前锁不存在,返回加锁成功



if (jedis.setnx(lockKey, expiresStr) == 1) {

return true;

}

// 如果锁存在,获取锁的过期时间



String currentValue = jedis.get(lockKey);

String currentValueStr = null==currentValue?null:currentValue.split("#")[1];

// 判断当前锁是否过期

if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {

// 锁已过期,获取上一个锁的过期时间,并设置现在锁的过期时间 此处多个客户端会覆盖锁的过期时间

String oldValue = jedis.getSet(lockKey,expiresStr);

String oldValueStr = null ==oldValue?null:oldValue.split("#")[1];

// 考虑多线程并发的情况,只有一个线程的设置值和当前值相同,它才有权利加锁

if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {

//由于上面会覆盖锁的过期时间 此处让获取锁的客户端 重新设置为自己的过期时间

jedis.set(lockKey,expiresStr);

return true;

}

}

// 其他情况,一律返回加锁失败

return false;

}

/**



*

* @param jedis

* @param lockKey 锁key

* @param value 过期时间 一般为 System.currentTimeMillis()+ 过期时间

* @return

*/

public static boolean releaseDistributedLock(Jedis jedis, String lockKey, long value) {

String uuid = LOCAL.get();

String valueStr = uuid+"#"+value;

//根据uuid 这个标识 让客户端 去释放自己的锁 不能释放别人的锁

if(valueStr.equals(jedis.get(lockKey))){

jedis.del(lockKey);

return true;

}

return false;

}

————————————————

版权声明:本文为CSDN博主「wudidewu」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/wudidewu/article/details/79817125