在有些需要高可用的場景中,保證併發量的情況下需要使用分布式鎖來做控制,保證應用的可靠性。我們知道jdk提供了一些常用的鎖比如reentrantlock,reentrantreadwritelock,synchronized。對於這些鎖的實現這裡就不詳細介紹了,在使用過程中這些鎖鎖的是物件,在單伺服器的時候有用。但是現在基本都不是單一伺服器了,一般都會有多台伺服器。對於一些要求高的業務,而且耗時長的任務,比如當客戶端乙個請求到a伺服器時,a伺服器還沒處理完,此時客戶端又請求b伺服器,對於一些非冪等操作,是不允許這樣操作的,比如請求第三方下單的時候,就必須保證只有第一次請求有結果後,才能進行第二次請求,否則可能存在重複下單的過程。這個時候就可以對整個下單過程加鎖,使用分布式鎖。
redis可以實現分布式鎖主要是redis為單程序單執行緒模式,採用佇列模式將併發訪問變成序列訪問,且多客戶端對redis的連線並不存在競爭關係。
使用redis實現分布式鎖主要使用的幾個命令:
setnx
當且僅當 key 不存在,將 key 的值設為 value ,並返回1;若給定的 key 已經存在,則 setnx 不做任何動作,並返回0。
getset命令
將給定 key 的值設為 value ,並返回 key 的舊值 (old value),當 key 存在但不是字串型別時,返回乙個錯誤,當key不存在時,返回nil。
get命令
返回 key 所關聯的字串值,如果 key 不存在那麼返回特殊值 nil 。
del命令
刪除給定的乙個或多個 key ,不存在的 key 會被忽略。
其中setnx和getset可以理解為原子操作,是同步的。
package com.xfl.boot.common.utils.concurrent;
import org.slf4j.logger;
import org.slf4j.logge***ctory;
import org.springframework.dao.dataacces***ception;
import org.springframework.data.redis.connection.redisconnection;
import org.springframework.data.redis.core.rediscallback;
import org.springframework.data.redis.core.stringredistemplate;
import org.springframework.data.redis.serializer.stringredisserializer;
/** * 分布式鎖
*/public
class
redislock
public
redislock(stringredistemplate redistemplate, string lockkey, int timeoutmsecs)
public
redislock(stringredistemplate redistemplate, string lockkey, int timeoutmsecs, int expiremsecs)
public string getlockkey()
public string get(final string key)
return serializer.deserialize(data);
}});
} catch (exception e) ", key);
}return obj != null ? obj.tostring() : null;
}public
boolean
setnx(final string key, final string value)
});} catch (exception e) ", key);
}return obj != null ? (boolean) obj : false;
}private string getset(final string key, final string value)
});} catch (exception e) ", key);
}return obj != null ? (string) obj : null;
}public
synchronized
boolean
lock() throws interruptedexception
string currentvaluestr = this.get(lockkey); // redis裡的時間
if (currentvaluestr != null && long.parselong(currentvaluestr) < system.currenttimemillis())
}timeout -= default_acquiry_resolution_millis;
// 延遲100 毫秒
thread.sleep(default_acquiry_resolution_millis);
}return
false;
}public
synchronized
void
unlock()
}}
參考資料:string key = "122456";
redislock lock = new redislock(stringredistemplate, key.tostring(),
1000, 2000);
try else
} catch (interruptedexception e) finally
分布式鎖 使用Redis實現分布式鎖
關於分布式鎖的實現,我的前一篇文章講解了如何使用zookeeper實現分布式鎖。關於分布式鎖的背景此處不再做贅述,我們直接討論下如何使用redis實現分布式鎖。關於redis,筆主不打算做長篇大論的介紹,只介紹下redis優秀的特性。支援豐富的資料型別,如string list map set zs...
使用Redis實現分布式鎖
網上大部分建議都是使用setnx,這個本身沒有什麼問題,因為低版本的redis中,只有這個命令可以互斥的set乙個key。但是隨著redis版本的公升高,提供了更多的命令來更好的滿足我們的需求。set keyvalue ex seconds px milliseconds nx xx 這可和你所知道...
使用redis實現分布式鎖
一.redis命令講解 setnx 命令 setnx的含義就是set if not exists,其主要有兩個引數 setnx key,value 該方法是原子的,如果key不存在,則設定當前key成功,返回1 如果當前key已經存在,則設定當前key失敗,返回0。get 命令 get key 獲取...