高并發(fā)架構(gòu)系列:分布式鎖的由來(lái)、特點(diǎn)及Redis分布式鎖的實(shí)現(xiàn)詳解

在很多場(chǎng)景中舞终,我們?yōu)榱吮WC數(shù)據(jù)的最終一致性轻庆,需要很多的技術(shù)方案來(lái)支持,比如分布式事務(wù)敛劝、分布式鎖等余爆。那具體什么是分布式鎖,分布式鎖應(yīng)用在哪些業(yè)務(wù)場(chǎng)景夸盟、如何來(lái)實(shí)現(xiàn)分布式鎖呢蛾方?今天來(lái)探討分布式鎖這個(gè)話題。

什么是分布式鎖

要介紹分布式鎖上陕,首先要提到與分布式鎖相對(duì)應(yīng)的是線程鎖桩砰、進(jìn)程鎖。

1.線程鎖

主要用來(lái)給方法释簿、代碼塊加鎖亚隅。當(dāng)某個(gè)方法或代碼使用鎖,在同一時(shí)刻僅有一個(gè)線程執(zhí)行該方法或該代碼段庶溶。線程鎖只在同一JVM中有效果煮纵,因?yàn)榫€程鎖的實(shí)現(xiàn)在根本上是依靠線程之間共享內(nèi)存實(shí)現(xiàn)的,比如Synchronized偏螺、Lock等行疏。

2.進(jìn)程鎖

為了控制同一操作系統(tǒng)中多個(gè)進(jìn)程訪問某個(gè)共享資源,因?yàn)檫M(jìn)程具有獨(dú)立性砖茸,各個(gè)進(jìn)程無(wú)法訪問其他進(jìn)程的資源隘擎,因此無(wú)法通過synchronized等線程鎖實(shí)現(xiàn)進(jìn)程鎖殴穴。

3.分布式鎖

當(dāng)多個(gè)進(jìn)程不在同一個(gè)系統(tǒng)中凉夯,用分布式鎖控制多個(gè)進(jìn)程對(duì)資源的訪問货葬。

分布式鎖的由來(lái)

在傳統(tǒng)單機(jī)部署的情況下,可以使用Java并發(fā)處理相關(guān)的API(如ReentrantLcok或synchronized)進(jìn)行互斥控制劲够。

但是在分布式系統(tǒng)后震桶,由于分布式系統(tǒng)多線程、多進(jìn)程并且分布在不同機(jī)器上征绎,這將使原單機(jī)并發(fā)控制鎖策略失效蹲姐,為了解決這個(gè)問題就需要一種跨JVM的互斥機(jī)制來(lái)控制共享資源的訪問,這就是分布式鎖的由來(lái)人柿。

當(dāng)多個(gè)進(jìn)程不在同一個(gè)系統(tǒng)中柴墩,就需要用分布式鎖控制多個(gè)進(jìn)程對(duì)資源的訪問。


分布式鎖的特點(diǎn)

首先凫岖,為了確保分布式鎖可用江咳,我們至少要確保鎖的實(shí)現(xiàn)同時(shí)滿足以下四個(gè)條件:

1、互斥性:任意時(shí)刻哥放,只能有一個(gè)客戶端獲取鎖歼指,不能同時(shí)有兩個(gè)客戶端獲取到鎖。

2甥雕、安全性:鎖只能被持有該鎖的客戶端刪除踩身,不能由其它客戶端刪除。

3社露、死鎖:獲取鎖的客戶端因?yàn)槟承┰颍ㄈ鏳own機(jī)等)而未能釋放鎖挟阻,其它客戶端再也無(wú)法獲取到該鎖。

4峭弟、容錯(cuò):當(dāng)部分節(jié)點(diǎn)(redis節(jié)點(diǎn)等)down機(jī)時(shí)赁濒,客戶端仍然能夠獲取鎖和釋放鎖。


分布式鎖的具體實(shí)現(xiàn)

分布式鎖一般有三種實(shí)現(xiàn)方式:

1. 數(shù)據(jù)庫(kù)樂觀鎖孟害;

2. 基于ZooKeeper的分布式鎖;

3.基于Redis的分布式鎖拒炎;


Redis實(shí)現(xiàn)分布式鎖

基于Redis命令:SET key value NX EX max-lock-time

這里補(bǔ)充下: 從2.6.12版本后, 就可以使用set來(lái)獲取鎖, Lua 腳本來(lái)釋放鎖。setnx是老黃歷了挨务,set命令nx,xx等參數(shù), 是為了實(shí)現(xiàn) setnx 的功能击你。

1.加鎖

public class RedisTool {

private static final String LOCK_SUCCESS = "OK";

private static final String SET_IF_NOT_EXIST = "NX";

private static final String SET_WITH_EXPIRE_TIME = "PX";

/**

* 嘗試獲取分布式鎖

*?@param?jedis Redis客戶端

*?@param?lockKey 鎖

*?@param?requestId 請(qǐng)求標(biāo)識(shí)

*?@param?expireTime 超期時(shí)間

*?@return?是否獲取成功

*/

public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {

String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);?

if (LOCK_SUCCESS.equals(result)) {return true;}return false;}

}

jedis.set(String key, String value, String nxxx, String expx, int time)

這個(gè)set()方法一共有五個(gè)形參:

第一個(gè)為key,我們使用key來(lái)當(dāng)鎖谎柄,因?yàn)閗ey是唯一的丁侄。

第二個(gè)為value,我們傳的是requestId朝巫,很多童鞋可能不明白鸿摇,有key作為鎖不就夠了嗎,為什么還要用到value劈猿?原因就是我們?cè)谏厦嬷v到可靠性時(shí)拙吉,分布式鎖要滿足第四個(gè)條件解鈴還須系鈴人潮孽,通過給value賦值為requestId,我們就知道這把鎖是哪個(gè)請(qǐng)求加的了筷黔,在解鎖的時(shí)候就可以有依據(jù)往史。requestId可以使用UUID.randomUUID().toString()方法生成。

第三個(gè)為nxxx佛舱,這個(gè)參數(shù)我們填的是NX椎例,意思是SET IF NOT EXIST,即當(dāng)key不存在時(shí)请祖,我們進(jìn)行set操作订歪;若key已經(jīng)存在,則不做任何操作肆捕;

第四個(gè)為expx陌粹,這個(gè)參數(shù)我們傳的是PX,意思是我們要給這個(gè)key加一個(gè)過期的設(shè)置福压,具體時(shí)間由第五個(gè)參數(shù)決定掏秩。

第五個(gè)為time,與第四個(gè)參數(shù)相呼應(yīng)荆姆,代表key的過期時(shí)間蒙幻。

總的來(lái)說,執(zhí)行上面的set()方法就只會(huì)導(dǎo)致兩種結(jié)果:1. 當(dāng)前沒有鎖(key不存在)胆筒,那么就進(jìn)行加鎖操作邮破,并對(duì)鎖設(shè)置個(gè)有效期,同時(shí)value表示加鎖的客戶端仆救。2. 已有鎖存在抒和,不做任何操作。

2.解鎖

public class RedisTool {

private static final Long RELEASE_SUCCESS = 1L;

/**

* 釋放分布式鎖

* @param jedis Redis客戶端

* @param lockKey 鎖

* @param requestId 請(qǐng)求標(biāo)識(shí)

* @return 是否釋放成功

*/

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

String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";?

Object result = jedis.eval(script, Collections.singletonList(lockKey),Collections.singletonList(requestId));if (RELEASE_SUCCESS.equals(result)) {return true;}return false;}

}

那么這段Lua代碼的功能是什么呢彤蔽?其實(shí)很簡(jiǎn)單摧莽,首先獲取鎖對(duì)應(yīng)的value值,檢查是否與requestId相等顿痪,如果相等則刪除鎖(解鎖)镊辕。

以上就是redis實(shí)現(xiàn)分布式鎖詳解,覺得不錯(cuò)請(qǐng)點(diǎn)贊支持蚁袭,歡迎留言或進(jìn)我的個(gè)人群179961551領(lǐng)取【架構(gòu)資料專題目合集90期】征懈、【BATJTMD大廠JAVA面試真題1000+】,本群專用于學(xué)習(xí)交流技術(shù)揩悄、分享面試機(jī)會(huì)卖哎,拒絕廣告,我也會(huì)在群內(nèi)不定期答題、探討亏娜。

最後編輯於
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末焕窝,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子照藻,更是在濱河造成了極大的恐慌袜啃,老刑警劉巖汗侵,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幸缕,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡晰韵,警方通過查閱死者的電腦和手機(jī)发乔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)雪猪,“玉大人栏尚,你說我怎么就攤上這事≈缓蓿” “怎么了译仗?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)官觅。 經(jīng)常有香客問我纵菌,道長(zhǎng),這世上最難降的妖魔是什么休涤? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任咱圆,我火速辦了婚禮,結(jié)果婚禮上功氨,老公的妹妹穿的比我還像新娘序苏。我一直安慰自己,他們只是感情好捷凄,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布忱详。 她就那樣靜靜地躺著,像睡著了一般跺涤。 火紅的嫁衣襯著肌膚如雪踱阿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天钦铁,我揣著相機(jī)與錄音软舌,去河邊找鬼。 笑死牛曹,一個(gè)胖子當(dāng)著我的面吹牛佛点,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼超营,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼鸳玩!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起演闭,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤不跟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后米碰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體窝革,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年吕座,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了虐译。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡吴趴,死狀恐怖漆诽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情锣枝,我是刑警寧澤厢拭,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站撇叁,受9級(jí)特大地震影響供鸠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜税朴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一回季、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧正林,春花似錦泡一、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至杈绸,卻和暖如春帖蔓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瞳脓。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工塑娇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人劫侧。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓埋酬,卻偏偏與公主長(zhǎng)得像哨啃,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子写妥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 前言 分布式鎖一般有三種實(shí)現(xiàn)方式:1. 數(shù)據(jù)庫(kù)樂觀鎖拳球;2. 基于Redis的分布式鎖;3. 基于ZooKeeper...
    程序員技術(shù)圈閱讀 3,802評(píng)論 4 80
  • 前言 單機(jī)環(huán)境下我們可以通過JAVA的Synchronized和Lock來(lái)實(shí)現(xiàn)進(jìn)程內(nèi)部的鎖珍特,但是隨著分布式應(yīng)用和集...
    Java黎先生閱讀 731評(píng)論 0 1
  • 前言 分布式鎖一般有三種實(shí)現(xiàn)方式:1. 數(shù)據(jù)庫(kù)樂觀鎖祝峻;2. 基于Redis的分布式鎖;3. 基于ZooKeeper...
    朦朧蜜桃閱讀 482評(píng)論 1 0
  • 雨林細(xì)雨閱讀 154評(píng)論 0 0
  • 最近幾天參加公司研討會(huì)扎筒,暫時(shí)停止更新簡(jiǎn)書動(dòng)態(tài)莱找,請(qǐng)見諒!明天晚上開始繼續(xù)更新砸琅!敬請(qǐng)關(guān)注宋距!謝謝關(guān)注我的每一個(gè)人轴踱!
    幸福D蘇眉閱讀 232評(píng)論 0 1