基於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