拜托,面試請不要再問我Redis分布式鎖的實(shí)現(xiàn)原理秉馏!【石杉的架構(gòu)筆記】

一耙旦、寫在前面

現(xiàn)在面試,一般都會(huì)聊聊分布式系統(tǒng)這塊的東西萝究。通常面試官都會(huì)從服務(wù)框架(Spring Cloud免都、Dubbo)聊起,一路聊到分布式事務(wù)帆竹、分布式鎖绕娘、ZooKeeper等知識(shí)。所以咱們這篇文章就來聊聊分布式鎖這塊知識(shí)栽连,具體的來看看Redis分布式鎖的實(shí)現(xiàn)原理险领。

說實(shí)話,如果在公司里落地生產(chǎn)環(huán)境用分布式鎖的時(shí)候,一定是會(huì)用開源類庫的绢陌,比如Redis分布式鎖挨下,一般就是用Redisson框架就好了,非常的簡便易用下面。

大家如果有興趣,可以去看看Redisson的官網(wǎng)绩聘,看看如何在項(xiàng)目中引入Redisson的依賴沥割,然后基于Redis實(shí)現(xiàn)分布式鎖的加鎖與釋放鎖。下面給大家看一段簡單的使用代碼片段凿菩,先直觀的感受一下:

怎么樣机杜,上面那段代碼,是不是感覺簡單的不行衅谷!此外椒拗,人家還支持redis單實(shí)例、redis哨兵获黔、redis cluster蚀苛、redis master-slave等各種部署架構(gòu),都可以給你完美實(shí)現(xiàn)玷氏。

二堵未、Redisson實(shí)現(xiàn)Redis分布式鎖的底層原理

好的,接下來就通過一張手繪圖盏触,給大家說說Redisson這個(gè)開源框架對Redis分布式鎖的實(shí)現(xiàn)原理渗蟹。

image.png

(1)加鎖機(jī)制

咱們來看上面那張圖,現(xiàn)在某個(gè)客戶端要加鎖赞辩。如果該客戶端面對的是一個(gè)redis cluster集群雌芽,他首先會(huì)根據(jù)hash節(jié)點(diǎn)選擇一臺(tái)機(jī)器。這里注意辨嗽,僅僅只是選擇一臺(tái)機(jī)器世落!這點(diǎn)很關(guān)鍵!緊接著糟需,就會(huì)發(fā)送一段lua腳本到redis上岛心,那段lua腳本如下所示:

image.png

為啥要用lua腳本呢?因?yàn)橐淮筵鐝?fù)雜的業(yè)務(wù)邏輯篮灼,可以通過封裝在lua腳本中發(fā)送給redis忘古,保證這段復(fù)雜業(yè)務(wù)邏輯執(zhí)行的原子性

那么诅诱,這段lua腳本是什么意思呢髓堪?這里KEYS[1]代表的是你加鎖的那個(gè)key,比如說:RLock lock = redisson.getLock("myLock");這里你自己設(shè)置了加鎖的那個(gè)鎖key就是“myLock”。

ARGV[1]代表的就是鎖key的默認(rèn)生存時(shí)間干旁,默認(rèn)30秒驶沼。ARGV[2]代表的是加鎖的客戶端的ID,類似于下面這樣:8743c9c0-0795-4907-87fd-6c719a6b4586:1

給大家解釋一下争群,第一段if判斷語句回怜,就是用“exists myLock”命令判斷一下,如果你要加鎖的那個(gè)鎖key不存在的話换薄,你就進(jìn)行加鎖玉雾。如何加鎖呢?很簡單轻要,用下面的命令:hset myLock

8743c9c0-0795-4907-87fd-6c719a6b4586:1 1复旬,通過這個(gè)命令設(shè)置一個(gè)hash數(shù)據(jù)結(jié)構(gòu),這行命令執(zhí)行后冲泥,會(huì)出現(xiàn)一個(gè)類似下面的數(shù)據(jù)結(jié)構(gòu):

image.png

上述就代表“8743c9c0-0795-4907-87fd-6c719a6b4586:1”這個(gè)客戶端對“myLock”這個(gè)鎖key完成了加鎖驹碍。接著會(huì)執(zhí)行“pexpire myLock 30000”命令,設(shè)置myLock這個(gè)鎖key的生存時(shí)間是30秒凡恍。好了志秃,到此為止,ok嚼酝,加鎖完成了洽损。

(2)鎖互斥機(jī)制

那么在這個(gè)時(shí)候,如果客戶端2來嘗試加鎖革半,執(zhí)行了同樣的一段lua腳本碑定,會(huì)咋樣呢?很簡單又官,第一個(gè)if判斷會(huì)執(zhí)行“exists myLock”延刘,發(fā)現(xiàn)myLock這個(gè)鎖key已經(jīng)存在了。接著第二個(gè)if判斷六敬,判斷一下碘赖,myLock鎖key的hash數(shù)據(jù)結(jié)構(gòu)中,是否包含客戶端2的ID外构,但是明顯不是的普泡,因?yàn)槟抢锇氖强蛻舳?的ID。

所以审编,客戶端2會(huì)獲取到pttl myLock返回的一個(gè)數(shù)字撼班,這個(gè)數(shù)字代表了myLock這個(gè)鎖key的剩余生存時(shí)間。比如還剩15000毫秒的生存時(shí)間垒酬。此時(shí)客戶端2會(huì)進(jìn)入一個(gè)while循環(huán)砰嘁,不停的嘗試加鎖件炉。

(3)watch dog自動(dòng)延期機(jī)制

客戶端1加鎖的鎖key默認(rèn)生存時(shí)間才30秒,如果超過了30秒矮湘,客戶端1還想一直持有這把鎖斟冕,怎么辦呢?

簡單缅阳!只要客戶端1一旦加鎖成功磕蛇,就會(huì)啟動(dòng)一個(gè)watch dog看門狗,他是一個(gè)后臺(tái)線程十办,會(huì)每隔10秒檢查一下秀撇,如果客戶端1還持有鎖key,那么就會(huì)不斷的延長鎖key的生存時(shí)間橘洞。

(4)可重入加鎖機(jī)制

那如果客戶端1都已經(jīng)持有了這把鎖了捌袜,結(jié)果可重入的加鎖會(huì)怎么樣呢说搅?比如下面這種代碼:

image.png

這時(shí)我們來分析一下上面那段lua腳本炸枣。第一個(gè)if判斷肯定不成立,“exists myLock”會(huì)顯示鎖key已經(jīng)存在了弄唧。第二個(gè)if判斷會(huì)成立适肠,因?yàn)閙yLock的hash數(shù)據(jù)結(jié)構(gòu)中包含的那個(gè)ID,就是客戶端1的那個(gè)ID候引,也就是“8743c9c0-0795-4907-87fd-6c719a6b4586:1”

此時(shí)就會(huì)執(zhí)行可重入加鎖的邏輯侯养,他會(huì)用:

incrby myLock 8743c9c0-0795-4907-87fd-6c71a6b4586:1 1 ,通過這個(gè)命令澄干,對客戶端1的加鎖次數(shù)逛揩,累加1。此時(shí)myLock數(shù)據(jù)結(jié)構(gòu)變?yōu)橄旅孢@樣:

image.png

大家看到了吧麸俘,那個(gè)myLock的hash數(shù)據(jù)結(jié)構(gòu)中的那個(gè)客戶端ID辩稽,就對應(yīng)著加鎖的次數(shù)

(5)釋放鎖機(jī)制

如果執(zhí)行l(wèi)ock.unlock(),就可以釋放分布式鎖从媚,此時(shí)的業(yè)務(wù)邏輯也是非常簡單的逞泄。其實(shí)說白了,就是每次都對myLock數(shù)據(jù)結(jié)構(gòu)中的那個(gè)加鎖次數(shù)減1拜效。如果發(fā)現(xiàn)加鎖次數(shù)是0了喷众,說明這個(gè)客戶端已經(jīng)不再持有鎖了,此時(shí)就會(huì)用:“del myLock”命令紧憾,從redis里刪除這個(gè)key到千。然后呢,另外的客戶端2就可以嘗試完成加鎖了赴穗。這就是所謂的分布式鎖的開源Redisson框架的實(shí)現(xiàn)機(jī)制父阻。

一般我們在生產(chǎn)系統(tǒng)中愈涩,可以用Redisson框架提供的這個(gè)類庫來基于redis進(jìn)行分布式鎖的加鎖與釋放鎖。

(6)上述Redis分布式鎖的缺點(diǎn)

其實(shí)上面那種方案最大的問題加矛,就是如果你對某個(gè)redis master實(shí)例履婉,寫入了myLock這種鎖key的value,此時(shí)會(huì)異步復(fù)制給對應(yīng)的master slave實(shí)例斟览。但是這個(gè)過程中一旦發(fā)生redis master宕機(jī)毁腿,主備切換,redis slave變?yōu)榱藃edis master苛茂。

接著就會(huì)導(dǎo)致已烤,客戶端2來嘗試加鎖的時(shí)候,在新的redis master上完成了加鎖妓羊,而客戶端1也以為自己成功加了鎖胯究。此時(shí)就會(huì)導(dǎo)致多個(gè)客戶端對一個(gè)分布式鎖完成了加鎖。這時(shí)系統(tǒng)在業(yè)務(wù)語義上一定會(huì)出現(xiàn)問題躁绸,導(dǎo)致各種臟數(shù)據(jù)的產(chǎn)生裕循。

所以這個(gè)就是redis cluster,或者是redis master-slave架構(gòu)的主從異步復(fù)制導(dǎo)致的redis分布式鎖的最大缺陷:在redis master實(shí)例宕機(jī)的時(shí)候净刮,可能導(dǎo)致多個(gè)客戶端同時(shí)完成加鎖剥哑。

作者:石杉的架構(gòu)筆記
鏈接:https://juejin.im/post/5bf3f15851882526a643e207
來源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)淹父,非商業(yè)轉(zhuǎn)載請注明出處株婴。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市暑认,隨后出現(xiàn)的幾起案子困介,更是在濱河造成了極大的恐慌,老刑警劉巖蘸际,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件座哩,死亡現(xiàn)場離奇詭異,居然都是意外死亡捡鱼,警方通過查閱死者的電腦和手機(jī)八回,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來驾诈,“玉大人缠诅,你說我怎么就攤上這事≌” “怎么了管引?”我有些...
    開封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長闯两。 經(jīng)常有香客問我褥伴,道長谅将,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任重慢,我火速辦了婚禮饥臂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘似踱。我一直安慰自己隅熙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開白布核芽。 她就那樣靜靜地躺著囚戚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪轧简。 梳的紋絲不亂的頭發(fā)上驰坊,一...
    開封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音哮独,去河邊找鬼拳芙。 笑死,一個(gè)胖子當(dāng)著我的面吹牛借嗽,可吹牛的內(nèi)容都是我干的态鳖。 我是一名探鬼主播转培,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼恶导,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了浸须?” 一聲冷哼從身側(cè)響起惨寿,我...
    開封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎删窒,沒想到半個(gè)月后裂垦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肌索,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年蕉拢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诚亚。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡晕换,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出站宗,到底是詐尸還是另有隱情闸准,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布梢灭,位于F島的核電站夷家,受9級(jí)特大地震影響蒸其,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜库快,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一摸袁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧义屏,春花似錦但惶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至阳啥,卻和暖如春添谊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背察迟。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來泰國打工斩狱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人扎瓶。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓所踊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親概荷。 傳聞我的和親對象是個(gè)殘疾皇子秕岛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351